blob: 4d7634f8ef474c635ef13d27acef72416b559143 [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
2070static int out_standby(struct audio_stream *stream)
2071{
2072 struct stream_out *out = (struct stream_out *)stream;
2073 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002074 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002075
Eric Laurent994a6932013-07-17 11:51:42 -07002076 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002077 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002078
Eric Laurenta1478072015-09-21 17:21:52 -07002079 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002081 if (adev->adm_deregister_stream)
2082 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002083 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002085 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2086 if (out->pcm) {
2087 pcm_close(out->pcm);
2088 out->pcm = NULL;
2089 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002090 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002091 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002092 out->playback_started = false;
2093 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002094 } else {
2095 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002096 out->gapless_mdata.encoder_delay = 0;
2097 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098 if (out->compr != NULL) {
2099 compress_close(out->compr);
2100 out->compr = NULL;
2101 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002102 }
Phil Burkbc991042017-02-24 08:06:44 -08002103 if (do_stop) {
2104 stop_output_stream(out);
2105 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002106 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107 }
2108 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002109 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 return 0;
2111}
2112
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002113static int out_on_error(struct audio_stream *stream)
2114{
2115 struct stream_out *out = (struct stream_out *)stream;
2116 struct audio_device *adev = out->dev;
2117 bool do_standby = false;
2118
2119 lock_output_stream(out);
2120 if (!out->standby) {
2121 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2122 stop_compressed_output_l(out);
2123 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2124 } else
2125 do_standby = true;
2126 }
2127 pthread_mutex_unlock(&out->lock);
2128
2129 if (do_standby)
2130 return out_standby(&out->stream.common);
2131
2132 return 0;
2133}
2134
Andy Hung7401c7c2016-09-21 12:41:21 -07002135static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136{
Andy Hung7401c7c2016-09-21 12:41:21 -07002137 struct stream_out *out = (struct stream_out *)stream;
2138
2139 // We try to get the lock for consistency,
2140 // but it isn't necessary for these variables.
2141 // If we're not in standby, we may be blocked on a write.
2142 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2143 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2144 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2145
2146 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002147 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002148 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002149
2150 // dump error info
2151 (void)error_log_dump(
2152 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002153 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002154 (void)power_log_dump(
2155 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156 return 0;
2157}
2158
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002159static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2160{
2161 int ret = 0;
2162 char value[32];
2163 struct compr_gapless_mdata tmp_mdata;
2164
2165 if (!out || !parms) {
2166 return -EINVAL;
2167 }
2168
2169 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2170 if (ret >= 0) {
2171 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2172 } else {
2173 return -EINVAL;
2174 }
2175
2176 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2177 if (ret >= 0) {
2178 tmp_mdata.encoder_padding = atoi(value);
2179 } else {
2180 return -EINVAL;
2181 }
2182
2183 out->gapless_mdata = tmp_mdata;
2184 out->send_new_metadata = 1;
2185 ALOGV("%s new encoder delay %u and padding %u", __func__,
2186 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2187
2188 return 0;
2189}
2190
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002191static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2192{
2193 return out == adev->primary_output || out == adev->voice_tx_output;
2194}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2197{
2198 struct stream_out *out = (struct stream_out *)stream;
2199 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002200 struct audio_usecase *usecase;
2201 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202 struct str_parms *parms;
2203 char value[32];
2204 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002205 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002206 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207
Eric Laurent2e140aa2016-06-30 17:14:46 -07002208 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002209 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 parms = str_parms_create_str(kvpairs);
2211 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2212 if (ret >= 0) {
2213 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002214 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002215 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002217 /*
2218 * When HDMI cable is unplugged the music playback is paused and
2219 * the policy manager sends routing=0. But the audioflinger
2220 * continues to write data until standby time (3sec).
2221 * As the HDMI core is turned off, the write gets blocked.
2222 * Avoid this by routing audio to speaker until standby.
2223 */
2224 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2225 val == AUDIO_DEVICE_NONE) {
2226 val = AUDIO_DEVICE_OUT_SPEAKER;
2227 }
2228
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002229 audio_devices_t new_dev = val;
2230
2231 // Workaround: If routing to an non existing usb device, fail gracefully
2232 // The routing request will otherwise block during 10 second
2233 if (audio_is_usb_out_device(new_dev) && !audio_extn_usb_alive(adev->snd_card)) {
2234 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d",
2235 adev->snd_card);
2236 pthread_mutex_unlock(&adev->lock);
2237 pthread_mutex_unlock(&out->lock);
2238 status = -ENOSYS;
2239 goto routing_fail;
2240 }
2241
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002242 /*
2243 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002244 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002245 * the select_devices(). But how do we undo this?
2246 *
2247 * For example, music playback is active on headset (deep-buffer usecase)
2248 * and if we go to ringtones and select a ringtone, low-latency usecase
2249 * will be started on headset+speaker. As we can't enable headset+speaker
2250 * and headset devices at the same time, select_devices() switches the music
2251 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2252 * So when the ringtone playback is completed, how do we undo the same?
2253 *
2254 * We are relying on the out_set_parameters() call on deep-buffer output,
2255 * once the ringtone playback is ended.
2256 * NOTE: We should not check if the current devices are same as new devices.
2257 * Because select_devices() must be called to switch back the music
2258 * playback to headset.
2259 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002260 if (new_dev != AUDIO_DEVICE_NONE) {
2261 bool same_dev = out->devices == new_dev;
2262 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002263
Eric Laurenta7657192014-10-09 21:09:33 -07002264 if (output_drives_call(adev, out)) {
2265 if (!voice_is_in_call(adev)) {
2266 if (adev->mode == AUDIO_MODE_IN_CALL) {
2267 adev->current_call_output = out;
2268 ret = voice_start_call(adev);
2269 }
2270 } else {
2271 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002272 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002273 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002274 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002275
2276 if (!out->standby) {
2277 if (!same_dev) {
2278 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002279 // inform adm before actual routing to prevent glitches.
2280 if (adev->adm_on_routing_change) {
2281 adev->adm_on_routing_change(adev->adm_data,
2282 out->handle);
2283 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002284 }
2285 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002286 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002287
2288 // on device switch force swap, lower functions will make sure
2289 // to check if swap is allowed or not.
2290
2291 if (!same_dev)
2292 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002293 }
2294
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002295 }
2296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002298 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002299
2300 /*handles device and call state changes*/
2301 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002302 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002303 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002304
2305 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2306 parse_compress_metadata(out, parms);
2307 }
2308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002309 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002310 ALOGV("%s: exit: code(%d)", __func__, status);
2311 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312}
2313
Haynes Mathew George569b7482017-05-08 14:44:27 -07002314static bool stream_get_parameter_channels(struct str_parms *query,
2315 struct str_parms *reply,
2316 audio_channel_mask_t *supported_channel_masks) {
2317 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002320 size_t i, j;
2321
2322 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2323 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324 value[0] = '\0';
2325 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002326 while (supported_channel_masks[i] != 0) {
2327 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2328 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329 if (!first) {
2330 strcat(value, "|");
2331 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002332 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002333 first = false;
2334 break;
2335 }
2336 }
2337 i++;
2338 }
2339 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002340 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002341 return ret >= 0;
2342}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002343
Haynes Mathew George569b7482017-05-08 14:44:27 -07002344static bool stream_get_parameter_formats(struct str_parms *query,
2345 struct str_parms *reply,
2346 audio_format_t *supported_formats) {
2347 int ret = -1;
2348 char value[256];
2349 int i;
2350
2351 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2352 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002353 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002354 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002355 case AUDIO_FORMAT_PCM_16_BIT:
2356 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2357 break;
2358 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2359 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2360 break;
2361 case AUDIO_FORMAT_PCM_32_BIT:
2362 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2363 break;
2364 default:
2365 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002366 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002367 break;
2368 }
2369 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002370 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002371 return ret >= 0;
2372}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002373
Haynes Mathew George569b7482017-05-08 14:44:27 -07002374static bool stream_get_parameter_rates(struct str_parms *query,
2375 struct str_parms *reply,
2376 uint32_t *supported_sample_rates) {
2377
2378 int i;
2379 char value[256];
2380 int ret = -1;
2381 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2382 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002383 value[0] = '\0';
2384 i=0;
2385 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002386 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002387 int avail = sizeof(value) - cursor;
2388 ret = snprintf(value + cursor, avail, "%s%d",
2389 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002390 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002391 if (ret < 0 || ret >= avail) {
2392 // if cursor is at the last element of the array
2393 // overwrite with \0 is duplicate work as
2394 // snprintf already put a \0 in place.
2395 // else
2396 // we had space to write the '|' at value[cursor]
2397 // (which will be overwritten) or no space to fill
2398 // the first element (=> cursor == 0)
2399 value[cursor] = '\0';
2400 break;
2401 }
2402 cursor += ret;
2403 ++i;
2404 }
2405 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2406 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002407 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002408 return ret >= 0;
2409}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002410
Haynes Mathew George569b7482017-05-08 14:44:27 -07002411static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2412{
2413 struct stream_out *out = (struct stream_out *)stream;
2414 struct str_parms *query = str_parms_create_str(keys);
2415 char *str;
2416 struct str_parms *reply = str_parms_create();
2417 bool replied = false;
2418 ALOGV("%s: enter: keys - %s", __func__, keys);
2419
2420 replied |= stream_get_parameter_channels(query, reply,
2421 &out->supported_channel_masks[0]);
2422 replied |= stream_get_parameter_formats(query, reply,
2423 &out->supported_formats[0]);
2424 replied |= stream_get_parameter_rates(query, reply,
2425 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002426 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427 str = str_parms_to_str(reply);
2428 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002429 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 }
2431 str_parms_destroy(query);
2432 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002433 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434 return str;
2435}
2436
2437static uint32_t out_get_latency(const struct audio_stream_out *stream)
2438{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002439 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440 struct stream_out *out = (struct stream_out *)stream;
2441
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002442 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2443 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002444 else if ((out->realtime) ||
2445 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002446 // since the buffer won't be filled up faster than realtime,
2447 // return a smaller number
2448 period_ms = (out->af_period_multiplier * out->config.period_size *
2449 1000) / (out->config.rate);
2450 hw_delay = platform_render_latency(out->usecase)/1000;
2451 return period_ms + hw_delay;
2452 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453
2454 return (out->config.period_count * out->config.period_size * 1000) /
2455 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002456}
2457
2458static int out_set_volume(struct audio_stream_out *stream, float left,
2459 float right)
2460{
Eric Laurenta9024de2013-04-04 09:19:12 -07002461 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002462 int volume[2];
2463
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002464 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002465 /* only take left channel into account: the API is for stereo anyway */
2466 out->muted = (left == 0.0f);
2467 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2469 const char *mixer_ctl_name = "Compress Playback Volume";
2470 struct audio_device *adev = out->dev;
2471 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002472 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2473 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002474 /* try with the control based on device id */
2475 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2476 PCM_PLAYBACK);
2477 char ctl_name[128] = {0};
2478 snprintf(ctl_name, sizeof(ctl_name),
2479 "Compress Playback %d Volume", pcm_device_id);
2480 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2481 if (!ctl) {
2482 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2483 return -EINVAL;
2484 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002485 }
2486 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2487 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2488 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2489 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002490 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002491 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2492 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2493 if (!out->standby) {
2494 // if in standby, cached volume will be sent after stream is opened
2495 audio_extn_utils_send_app_type_gain(out->dev,
2496 out->app_type_cfg.app_type,
2497 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002498 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002499 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002500 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002501
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 return -ENOSYS;
2503}
2504
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002505// note: this call is safe only if the stream_cb is
2506// removed first in close_output_stream (as is done now).
2507static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2508{
2509 if (!stream || !parms)
2510 return;
2511
2512 struct stream_out *out = (struct stream_out *)stream;
2513 struct audio_device *adev = out->dev;
2514
2515 card_status_t status;
2516 int card;
2517 if (parse_snd_card_status(parms, &card, &status) < 0)
2518 return;
2519
2520 pthread_mutex_lock(&adev->lock);
2521 bool valid_cb = (card == adev->snd_card);
2522 pthread_mutex_unlock(&adev->lock);
2523
2524 if (!valid_cb)
2525 return;
2526
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002527 lock_output_stream(out);
2528 if (out->card_status != status)
2529 out->card_status = status;
2530 pthread_mutex_unlock(&out->lock);
2531
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002532 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2533 use_case_table[out->usecase],
2534 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2535
2536 if (status == CARD_STATUS_OFFLINE)
2537 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002538
2539 return;
2540}
2541
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002542#ifdef NO_AUDIO_OUT
2543static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002544 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002545{
2546 struct stream_out *out = (struct stream_out *)stream;
2547
2548 /* No Output device supported other than BT for playback.
2549 * Sleep for the amount of buffer duration
2550 */
Eric Laurenta1478072015-09-21 17:21:52 -07002551 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002552 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2553 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002554 out_get_sample_rate(&out->stream.common));
2555 pthread_mutex_unlock(&out->lock);
2556 return bytes;
2557}
2558#endif
2559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2561 size_t bytes)
2562{
2563 struct stream_out *out = (struct stream_out *)stream;
2564 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002565 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002566 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567
Eric Laurenta1478072015-09-21 17:21:52 -07002568 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002569 // this is always nonzero
Andy Hung928efbe2017-06-12 14:05:22 -07002570 const size_t frame_size = audio_stream_out_frame_size(stream);
2571 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002572
Eric Laurent0e46adf2016-12-16 12:49:24 -08002573 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2574 error_code = ERROR_CODE_WRITE;
2575 goto exit;
2576 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002578 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002579 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002580 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002581 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002584 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 goto exit;
2586 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002587
2588 if (last_known_cal_step != -1) {
2589 ALOGD("%s: retry previous failed cal level set", __func__);
2590 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2591 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002594 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002595 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002596 if (out->send_new_metadata) {
2597 ALOGVV("send new gapless metadata");
2598 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2599 out->send_new_metadata = 0;
2600 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002601 unsigned int avail;
2602 struct timespec tstamp;
2603 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2604 /* Do not limit write size if the available frames count is unknown */
2605 if (ret != 0) {
2606 avail = bytes;
2607 }
2608 if (avail == 0) {
2609 ret = 0;
2610 } else {
2611 if (avail > bytes) {
2612 avail = bytes;
2613 }
2614 ret = compress_write(out->compr, buffer, avail);
2615 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2616 __func__, avail, ret);
2617 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002618
Eric Laurent6e895242013-09-05 16:10:57 -07002619 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002620 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2621 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002622 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002623 compress_start(out->compr);
2624 out->playback_started = 1;
2625 out->offload_state = OFFLOAD_STATE_PLAYING;
2626 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002627 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002628 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002629 } else {
2630 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002631 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002632 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002633 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002634 return ret;
2635 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002636 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002637 if (out->pcm) {
2638 if (out->muted)
2639 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002640
Eric Laurent0e46adf2016-12-16 12:49:24 -08002641 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002642
Haynes Mathew George03c40102016-01-29 17:57:48 -08002643 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2644 out->config.rate;
2645 request_out_focus(out, ns);
2646
2647 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2648 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002649 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002650 else
2651 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002652
Haynes Mathew George03c40102016-01-29 17:57:48 -08002653 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002654 } else {
2655 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 }
2658
2659exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002660 // For PCM we always consume the buffer and return #bytes regardless of ret.
2661 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung928efbe2017-06-12 14:05:22 -07002662 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002663 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002664 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002665
2666 // only get time if needed for logging, as it is a system call on 32 bit devices.
2667 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2668 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2669 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002670
Andy Hung7401c7c2016-09-21 12:41:21 -07002671 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002672 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002673 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2674 ALOGE_IF(out->pcm != NULL,
2675 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung928efbe2017-06-12 14:05:22 -07002676 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002677 // usleep not guaranteed for values over 1 second but we don't limit here.
2678 }
2679 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 pthread_mutex_unlock(&out->lock);
2682
2683 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002684 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002685 if (sleeptime_us != 0)
2686 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002687 } else {
2688 // only log if the data is properly written (out->power_log may be null)
Andy Hung928efbe2017-06-12 14:05:22 -07002689 power_log_log(out->power_log, buffer, frames, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 }
2691 return bytes;
2692}
2693
2694static int out_get_render_position(const struct audio_stream_out *stream,
2695 uint32_t *dsp_frames)
2696{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002697 struct stream_out *out = (struct stream_out *)stream;
2698 *dsp_frames = 0;
2699 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002700 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002701 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002702 unsigned long frames = 0;
2703 // TODO: check return value
2704 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2705 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002706 ALOGVV("%s rendered frames %d sample_rate %d",
2707 __func__, *dsp_frames, out->sample_rate);
2708 }
2709 pthread_mutex_unlock(&out->lock);
2710 return 0;
2711 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002712 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713}
2714
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002715static int out_add_audio_effect(const struct audio_stream *stream __unused,
2716 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717{
2718 return 0;
2719}
2720
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002721static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2722 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002723{
2724 return 0;
2725}
2726
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002727static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2728 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002729{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002730 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731}
2732
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002733static int out_get_presentation_position(const struct audio_stream_out *stream,
2734 uint64_t *frames, struct timespec *timestamp)
2735{
2736 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002737 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002738 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002739
Eric Laurenta1478072015-09-21 17:21:52 -07002740 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002741
Eric Laurent949a0892013-09-20 09:20:13 -07002742 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2743 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002744 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002745 compress_get_tstamp(out->compr, &dsp_frames,
2746 &out->sample_rate);
2747 ALOGVV("%s rendered frames %ld sample_rate %d",
2748 __func__, dsp_frames, out->sample_rate);
2749 *frames = dsp_frames;
2750 ret = 0;
2751 /* this is the best we can do */
2752 clock_gettime(CLOCK_MONOTONIC, timestamp);
2753 }
2754 } else {
2755 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002756 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002757 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2758 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002759 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002760 // This adjustment accounts for buffering after app processor.
2761 // It is based on estimated DSP latency per use case, rather than exact.
2762 signed_frames -=
2763 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2764
Eric Laurent949a0892013-09-20 09:20:13 -07002765 // It would be unusual for this value to be negative, but check just in case ...
2766 if (signed_frames >= 0) {
2767 *frames = signed_frames;
2768 ret = 0;
2769 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002770 }
2771 }
2772 }
2773
2774 pthread_mutex_unlock(&out->lock);
2775
2776 return ret;
2777}
2778
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002779static int out_set_callback(struct audio_stream_out *stream,
2780 stream_callback_t callback, void *cookie)
2781{
2782 struct stream_out *out = (struct stream_out *)stream;
2783
2784 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002785 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002786 out->offload_callback = callback;
2787 out->offload_cookie = cookie;
2788 pthread_mutex_unlock(&out->lock);
2789 return 0;
2790}
2791
2792static int out_pause(struct audio_stream_out* stream)
2793{
2794 struct stream_out *out = (struct stream_out *)stream;
2795 int status = -ENOSYS;
2796 ALOGV("%s", __func__);
2797 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002798 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2800 status = compress_pause(out->compr);
2801 out->offload_state = OFFLOAD_STATE_PAUSED;
2802 }
2803 pthread_mutex_unlock(&out->lock);
2804 }
2805 return status;
2806}
2807
2808static int out_resume(struct audio_stream_out* stream)
2809{
2810 struct stream_out *out = (struct stream_out *)stream;
2811 int status = -ENOSYS;
2812 ALOGV("%s", __func__);
2813 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2814 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002815 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002816 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2817 status = compress_resume(out->compr);
2818 out->offload_state = OFFLOAD_STATE_PLAYING;
2819 }
2820 pthread_mutex_unlock(&out->lock);
2821 }
2822 return status;
2823}
2824
2825static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2826{
2827 struct stream_out *out = (struct stream_out *)stream;
2828 int status = -ENOSYS;
2829 ALOGV("%s", __func__);
2830 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002831 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2833 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2834 else
2835 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2836 pthread_mutex_unlock(&out->lock);
2837 }
2838 return status;
2839}
2840
2841static int out_flush(struct audio_stream_out* stream)
2842{
2843 struct stream_out *out = (struct stream_out *)stream;
2844 ALOGV("%s", __func__);
2845 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002846 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847 stop_compressed_output_l(out);
2848 pthread_mutex_unlock(&out->lock);
2849 return 0;
2850 }
2851 return -ENOSYS;
2852}
2853
Eric Laurent0e46adf2016-12-16 12:49:24 -08002854static int out_stop(const struct audio_stream_out* stream)
2855{
2856 struct stream_out *out = (struct stream_out *)stream;
2857 struct audio_device *adev = out->dev;
2858 int ret = -ENOSYS;
2859
2860 ALOGV("%s", __func__);
2861 pthread_mutex_lock(&adev->lock);
2862 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2863 out->playback_started && out->pcm != NULL) {
2864 pcm_stop(out->pcm);
2865 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002866 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002867 }
2868 pthread_mutex_unlock(&adev->lock);
2869 return ret;
2870}
2871
2872static int out_start(const struct audio_stream_out* stream)
2873{
2874 struct stream_out *out = (struct stream_out *)stream;
2875 struct audio_device *adev = out->dev;
2876 int ret = -ENOSYS;
2877
2878 ALOGV("%s", __func__);
2879 pthread_mutex_lock(&adev->lock);
2880 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2881 !out->playback_started && out->pcm != NULL) {
2882 ret = start_output_stream(out);
2883 if (ret == 0) {
2884 out->playback_started = true;
2885 }
2886 }
2887 pthread_mutex_unlock(&adev->lock);
2888 return ret;
2889}
2890
Phil Burkbc991042017-02-24 08:06:44 -08002891/*
2892 * Modify config->period_count based on min_size_frames
2893 */
2894static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2895{
2896 int periodCountRequested = (min_size_frames + config->period_size - 1)
2897 / config->period_size;
2898 int periodCount = MMAP_PERIOD_COUNT_MIN;
2899
2900 ALOGV("%s original config.period_size = %d config.period_count = %d",
2901 __func__, config->period_size, config->period_count);
2902
2903 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2904 periodCount *= 2;
2905 }
2906 config->period_count = periodCount;
2907
2908 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2909}
2910
Eric Laurent0e46adf2016-12-16 12:49:24 -08002911static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2912 int32_t min_size_frames,
2913 struct audio_mmap_buffer_info *info)
2914{
2915 struct stream_out *out = (struct stream_out *)stream;
2916 struct audio_device *adev = out->dev;
2917 int ret = 0;
2918 unsigned int offset1;
2919 unsigned int frames1;
2920 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002921 uint32_t mmap_size;
2922 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002923
2924 ALOGV("%s", __func__);
2925 pthread_mutex_lock(&adev->lock);
2926
2927 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002928 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002929 ret = -EINVAL;
2930 goto exit;
2931 }
2932 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002933 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002934 ret = -ENOSYS;
2935 goto exit;
2936 }
2937 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2938 if (out->pcm_device_id < 0) {
2939 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2940 __func__, out->pcm_device_id, out->usecase);
2941 ret = -EINVAL;
2942 goto exit;
2943 }
Phil Burkbc991042017-02-24 08:06:44 -08002944
2945 adjust_mmap_period_count(&out->config, min_size_frames);
2946
Eric Laurent0e46adf2016-12-16 12:49:24 -08002947 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2948 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2949 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2950 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2951 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2952 step = "open";
2953 ret = -ENODEV;
2954 goto exit;
2955 }
2956 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2957 if (ret < 0) {
2958 step = "begin";
2959 goto exit;
2960 }
2961 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002962 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002963 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002964 ret = platform_get_mmap_data_fd(adev->platform,
2965 out->pcm_device_id, 0 /*playback*/,
2966 &info->shared_memory_fd,
2967 &mmap_size);
2968 if (ret < 0) {
2969 // Fall back to non exclusive mode
2970 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2971 } else {
2972 if (mmap_size < buffer_size) {
2973 step = "mmap";
2974 goto exit;
2975 }
2976 // FIXME: indicate exclusive mode support by returning a negative buffer size
2977 info->buffer_size_frames *= -1;
2978 }
2979 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002980
2981 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2982 if (ret < 0) {
2983 step = "commit";
2984 goto exit;
2985 }
Phil Burkbc991042017-02-24 08:06:44 -08002986
2987 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002988 ret = 0;
2989
2990 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2991 __func__, info->shared_memory_address, info->buffer_size_frames);
2992
2993exit:
2994 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002995 if (out->pcm == NULL) {
2996 ALOGE("%s: %s - %d", __func__, step, ret);
2997 } else {
2998 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002999 pcm_close(out->pcm);
3000 out->pcm = NULL;
3001 }
3002 }
3003 pthread_mutex_unlock(&adev->lock);
3004 return ret;
3005}
3006
3007static int out_get_mmap_position(const struct audio_stream_out *stream,
3008 struct audio_mmap_position *position)
3009{
3010 struct stream_out *out = (struct stream_out *)stream;
3011 ALOGVV("%s", __func__);
3012 if (position == NULL) {
3013 return -EINVAL;
3014 }
3015 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
3016 return -ENOSYS;
3017 }
3018 if (out->pcm == NULL) {
3019 return -ENOSYS;
3020 }
3021
3022 struct timespec ts = { 0, 0 };
3023 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
3024 if (ret < 0) {
3025 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3026 return ret;
3027 }
Andy Hungfc044e12017-03-20 09:24:22 -07003028 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003029 return 0;
3030}
3031
3032
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033/** audio_stream_in implementation **/
3034static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3035{
3036 struct stream_in *in = (struct stream_in *)stream;
3037
3038 return in->config.rate;
3039}
3040
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003041static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042{
3043 return -ENOSYS;
3044}
3045
3046static size_t in_get_buffer_size(const struct audio_stream *stream)
3047{
3048 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003049 return in->config.period_size * in->af_period_multiplier *
3050 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051}
3052
3053static uint32_t in_get_channels(const struct audio_stream *stream)
3054{
3055 struct stream_in *in = (struct stream_in *)stream;
3056
3057 return in->channel_mask;
3058}
3059
vivek mehta4ed66e62016-04-15 23:33:34 -07003060static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061{
vivek mehta4ed66e62016-04-15 23:33:34 -07003062 struct stream_in *in = (struct stream_in *)stream;
3063 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064}
3065
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003066static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067{
3068 return -ENOSYS;
3069}
3070
3071static int in_standby(struct audio_stream *stream)
3072{
3073 struct stream_in *in = (struct stream_in *)stream;
3074 struct audio_device *adev = in->dev;
3075 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003076 bool do_stop = true;
3077
Eric Laurent994a6932013-07-17 11:51:42 -07003078 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003079
3080 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003081
3082 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003083 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003084 audio_extn_sound_trigger_stop_lab(in);
3085 in->standby = true;
3086 }
3087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003089 if (adev->adm_deregister_stream)
3090 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3091
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003092 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003093 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003094 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003095 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003096 in->capture_started = false;
3097 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003098 if (in->pcm) {
3099 pcm_close(in->pcm);
3100 in->pcm = NULL;
3101 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003102 adev->enable_voicerx = false;
3103 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003104 if (do_stop) {
3105 status = stop_input_stream(in);
3106 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003107 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108 }
3109 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003110 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 return status;
3112}
3113
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003114static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115{
3116 return 0;
3117}
3118
3119static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3120{
3121 struct stream_in *in = (struct stream_in *)stream;
3122 struct audio_device *adev = in->dev;
3123 struct str_parms *parms;
3124 char *str;
3125 char value[32];
3126 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003127 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128
Eric Laurent994a6932013-07-17 11:51:42 -07003129 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130 parms = str_parms_create_str(kvpairs);
3131
3132 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3133
Eric Laurenta1478072015-09-21 17:21:52 -07003134 lock_input_stream(in);
3135
Eric Laurent150dbfe2013-02-27 14:31:02 -08003136 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 if (ret >= 0) {
3138 val = atoi(value);
3139 /* no audio source uses val == 0 */
3140 if ((in->source != val) && (val != 0)) {
3141 in->source = val;
3142 }
3143 }
3144
3145 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147 if (ret >= 0) {
3148 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003149 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003150
3151 // Workaround: If routing to an non existing usb device, fail gracefully
3152 // The routing request will otherwise block during 10 second
3153 if (audio_is_usb_in_device(val) && !audio_extn_usb_alive(adev->snd_card)) {
3154 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d",
3155 adev->snd_card);
3156 status = -ENOSYS;
3157 } else {
3158
3159 in->device = val;
3160 /* If recording is in progress, change the tx device to new device */
3161 if (!in->standby) {
3162 ALOGV("update input routing change");
3163 // inform adm before actual routing to prevent glitches.
3164 if (adev->adm_on_routing_change) {
3165 adev->adm_on_routing_change(adev->adm_data,
3166 in->capture_handle);
3167 }
3168 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003169 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003170 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 }
3172 }
3173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003175 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176
3177 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003178 ALOGV("%s: exit: status(%d)", __func__, status);
3179 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180}
3181
Haynes Mathew George569b7482017-05-08 14:44:27 -07003182static char* in_get_parameters(const struct audio_stream *stream,
3183 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003184{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003185 struct stream_in *in = (struct stream_in *)stream;
3186 struct str_parms *query = str_parms_create_str(keys);
3187 char *str;
3188 struct str_parms *reply = str_parms_create();
3189 bool replied = false;
3190
3191 ALOGV("%s: enter: keys - %s", __func__, keys);
3192 replied |= stream_get_parameter_channels(query, reply,
3193 &in->supported_channel_masks[0]);
3194 replied |= stream_get_parameter_formats(query, reply,
3195 &in->supported_formats[0]);
3196 replied |= stream_get_parameter_rates(query, reply,
3197 &in->supported_sample_rates[0]);
3198 if (replied) {
3199 str = str_parms_to_str(reply);
3200 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003201 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003202 }
3203 str_parms_destroy(query);
3204 str_parms_destroy(reply);
3205 ALOGV("%s: exit: returns - %s", __func__, str);
3206 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207}
3208
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003209static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003211 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212}
3213
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003214static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3215{
3216 if (!stream || !parms)
3217 return;
3218
3219 struct stream_in *in = (struct stream_in *)stream;
3220 struct audio_device *adev = in->dev;
3221
3222 card_status_t status;
3223 int card;
3224 if (parse_snd_card_status(parms, &card, &status) < 0)
3225 return;
3226
3227 pthread_mutex_lock(&adev->lock);
3228 bool valid_cb = (card == adev->snd_card);
3229 pthread_mutex_unlock(&adev->lock);
3230
3231 if (!valid_cb)
3232 return;
3233
3234 lock_input_stream(in);
3235 if (in->card_status != status)
3236 in->card_status = status;
3237 pthread_mutex_unlock(&in->lock);
3238
3239 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3240 use_case_table[in->usecase],
3241 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3242
3243 // a better solution would be to report error back to AF and let
3244 // it put the stream to standby
3245 if (status == CARD_STATUS_OFFLINE)
3246 in_standby(&in->stream.common);
3247
3248 return;
3249}
3250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003251static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3252 size_t bytes)
3253{
3254 struct stream_in *in = (struct stream_in *)stream;
3255 struct audio_device *adev = in->dev;
3256 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003257 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258
Eric Laurenta1478072015-09-21 17:21:52 -07003259 lock_input_stream(in);
Andy Hung928efbe2017-06-12 14:05:22 -07003260 const size_t frame_size = audio_stream_in_frame_size(stream);
3261 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003262
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003263 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003264 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003265 /* Read from sound trigger HAL */
3266 audio_extn_sound_trigger_read(in, buffer, bytes);
3267 pthread_mutex_unlock(&in->lock);
3268 return bytes;
3269 }
3270
Eric Laurent0e46adf2016-12-16 12:49:24 -08003271 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3272 ret = -ENOSYS;
3273 goto exit;
3274 }
3275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003277 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003279 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281 goto exit;
3282 }
3283 in->standby = 0;
3284 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285
Haynes Mathew George03c40102016-01-29 17:57:48 -08003286 //what's the duration requested by the client?
3287 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3288 in->config.rate;
3289 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003290
Haynes Mathew George03c40102016-01-29 17:57:48 -08003291 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003293 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003294 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003295 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003296 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003297 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003298 if (ret < 0) {
3299 ALOGE("Failed to read w/err %s", strerror(errno));
3300 ret = -errno;
3301 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003302 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3303 if (bytes % 4 == 0) {
3304 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3305 int_buf_stream = buffer;
3306 for (size_t itt=0; itt < bytes/4 ; itt++) {
3307 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003308 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003309 } else {
3310 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3311 ret = -EINVAL;
3312 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003313 }
3314 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315 }
3316
Haynes Mathew George03c40102016-01-29 17:57:48 -08003317 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 /*
3320 * Instead of writing zeroes here, we could trust the hardware
3321 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003322 * 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 -08003323 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003324 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325 memset(buffer, 0, bytes);
3326
3327exit:
3328 pthread_mutex_unlock(&in->lock);
3329
3330 if (ret != 0) {
3331 in_standby(&in->stream.common);
3332 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung928efbe2017-06-12 14:05:22 -07003333 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003334 memset(buffer, 0, bytes); // clear return data
3335 }
3336 if (bytes > 0) {
Andy Hung928efbe2017-06-12 14:05:22 -07003337 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 }
3339 return bytes;
3340}
3341
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003342static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343{
3344 return 0;
3345}
3346
Andy Hung6ebe5962016-01-15 17:46:57 -08003347static int in_get_capture_position(const struct audio_stream_in *stream,
3348 int64_t *frames, int64_t *time)
3349{
3350 if (stream == NULL || frames == NULL || time == NULL) {
3351 return -EINVAL;
3352 }
3353 struct stream_in *in = (struct stream_in *)stream;
3354 int ret = -ENOSYS;
3355
3356 lock_input_stream(in);
3357 if (in->pcm) {
3358 struct timespec timestamp;
3359 unsigned int avail;
3360 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3361 *frames = in->frames_read + avail;
3362 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3363 ret = 0;
3364 }
3365 }
3366 pthread_mutex_unlock(&in->lock);
3367 return ret;
3368}
3369
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003370static int add_remove_audio_effect(const struct audio_stream *stream,
3371 effect_handle_t effect,
3372 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003374 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003375 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003376 int status = 0;
3377 effect_descriptor_t desc;
3378
3379 status = (*effect)->get_descriptor(effect, &desc);
3380 if (status != 0)
3381 return status;
3382
Eric Laurenta1478072015-09-21 17:21:52 -07003383 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003384 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003385 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003386 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003387 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003388 in->enable_aec != enable &&
3389 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3390 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003391 if (!enable)
3392 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003393 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3394 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3395 adev->enable_voicerx = enable;
3396 struct audio_usecase *usecase;
3397 struct listnode *node;
3398 list_for_each(node, &adev->usecase_list) {
3399 usecase = node_to_item(node, struct audio_usecase, list);
3400 if (usecase->type == PCM_PLAYBACK) {
3401 select_devices(adev, usecase->id);
3402 break;
3403 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003404 }
3405 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003406 if (!in->standby)
3407 select_devices(in->dev, in->usecase);
3408 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003409 if (in->enable_ns != enable &&
3410 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3411 in->enable_ns = enable;
3412 if (!in->standby)
3413 select_devices(in->dev, in->usecase);
3414 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003415 pthread_mutex_unlock(&in->dev->lock);
3416 pthread_mutex_unlock(&in->lock);
3417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 return 0;
3419}
3420
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003421static int in_add_audio_effect(const struct audio_stream *stream,
3422 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423{
Eric Laurent994a6932013-07-17 11:51:42 -07003424 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003425 return add_remove_audio_effect(stream, effect, true);
3426}
3427
3428static int in_remove_audio_effect(const struct audio_stream *stream,
3429 effect_handle_t effect)
3430{
Eric Laurent994a6932013-07-17 11:51:42 -07003431 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003432 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003433}
3434
Eric Laurent0e46adf2016-12-16 12:49:24 -08003435static int in_stop(const struct audio_stream_in* stream)
3436{
3437 struct stream_in *in = (struct stream_in *)stream;
3438 struct audio_device *adev = in->dev;
3439
3440 int ret = -ENOSYS;
3441 ALOGV("%s", __func__);
3442 pthread_mutex_lock(&adev->lock);
3443 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3444 in->capture_started && in->pcm != NULL) {
3445 pcm_stop(in->pcm);
3446 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003447 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003448 }
3449 pthread_mutex_unlock(&adev->lock);
3450 return ret;
3451}
3452
3453static int in_start(const struct audio_stream_in* stream)
3454{
3455 struct stream_in *in = (struct stream_in *)stream;
3456 struct audio_device *adev = in->dev;
3457 int ret = -ENOSYS;
3458
3459 ALOGV("%s in %p", __func__, in);
3460 pthread_mutex_lock(&adev->lock);
3461 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3462 !in->capture_started && in->pcm != NULL) {
3463 if (!in->capture_started) {
3464 ret = start_input_stream(in);
3465 if (ret == 0) {
3466 in->capture_started = true;
3467 }
3468 }
3469 }
3470 pthread_mutex_unlock(&adev->lock);
3471 return ret;
3472}
3473
3474static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3475 int32_t min_size_frames,
3476 struct audio_mmap_buffer_info *info)
3477{
3478 struct stream_in *in = (struct stream_in *)stream;
3479 struct audio_device *adev = in->dev;
3480 int ret = 0;
3481 unsigned int offset1;
3482 unsigned int frames1;
3483 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003484 uint32_t mmap_size;
3485 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003486
3487 pthread_mutex_lock(&adev->lock);
3488 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003489
Eric Laurent0e46adf2016-12-16 12:49:24 -08003490 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003491 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003492 ret = -EINVAL;
3493 goto exit;
3494 }
3495 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003496 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003497 ALOGV("%s in %p", __func__, in);
3498 ret = -ENOSYS;
3499 goto exit;
3500 }
3501 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3502 if (in->pcm_device_id < 0) {
3503 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3504 __func__, in->pcm_device_id, in->usecase);
3505 ret = -EINVAL;
3506 goto exit;
3507 }
Phil Burkbc991042017-02-24 08:06:44 -08003508
3509 adjust_mmap_period_count(&in->config, min_size_frames);
3510
Eric Laurent0e46adf2016-12-16 12:49:24 -08003511 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3512 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3513 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3514 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3515 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3516 step = "open";
3517 ret = -ENODEV;
3518 goto exit;
3519 }
3520
3521 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3522 if (ret < 0) {
3523 step = "begin";
3524 goto exit;
3525 }
3526 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003527 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003528 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003529 ret = platform_get_mmap_data_fd(adev->platform,
3530 in->pcm_device_id, 1 /*capture*/,
3531 &info->shared_memory_fd,
3532 &mmap_size);
3533 if (ret < 0) {
3534 // Fall back to non exclusive mode
3535 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3536 } else {
3537 if (mmap_size < buffer_size) {
3538 step = "mmap";
3539 goto exit;
3540 }
3541 // FIXME: indicate exclusive mode support by returning a negative buffer size
3542 info->buffer_size_frames *= -1;
3543 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003544
Haynes Mathew George96483a22017-03-28 14:52:47 -07003545 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003546
3547 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3548 if (ret < 0) {
3549 step = "commit";
3550 goto exit;
3551 }
3552
Phil Burkbc991042017-02-24 08:06:44 -08003553 in->standby = false;
3554 ret = 0;
3555
Eric Laurent0e46adf2016-12-16 12:49:24 -08003556 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3557 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003558
3559exit:
3560 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003561 if (in->pcm == NULL) {
3562 ALOGE("%s: %s - %d", __func__, step, ret);
3563 } else {
3564 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003565 pcm_close(in->pcm);
3566 in->pcm = NULL;
3567 }
3568 }
3569 pthread_mutex_unlock(&adev->lock);
3570 return ret;
3571}
3572
3573static int in_get_mmap_position(const struct audio_stream_in *stream,
3574 struct audio_mmap_position *position)
3575{
3576 struct stream_in *in = (struct stream_in *)stream;
3577 ALOGVV("%s", __func__);
3578 if (position == NULL) {
3579 return -EINVAL;
3580 }
3581 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3582 return -ENOSYS;
3583 }
3584 if (in->pcm == NULL) {
3585 return -ENOSYS;
3586 }
3587 struct timespec ts = { 0, 0 };
3588 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3589 if (ret < 0) {
3590 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3591 return ret;
3592 }
Andy Hungfc044e12017-03-20 09:24:22 -07003593 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003594 return 0;
3595}
3596
3597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003598static int adev_open_output_stream(struct audio_hw_device *dev,
3599 audio_io_handle_t handle,
3600 audio_devices_t devices,
3601 audio_output_flags_t flags,
3602 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003603 struct audio_stream_out **stream_out,
3604 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003605{
3606 struct audio_device *adev = (struct audio_device *)dev;
3607 struct stream_out *out;
3608 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003609 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3610 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3611 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3612 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003613
Andy Hungd9653bd2017-08-01 19:31:39 -07003614 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3615 return -ENOSYS;
3616 }
3617
Eric Laurent994a6932013-07-17 11:51:42 -07003618 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619 __func__, config->sample_rate, config->channel_mask, devices, flags);
3620 *stream_out = NULL;
3621 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3622
3623 if (devices == AUDIO_DEVICE_NONE)
3624 devices = AUDIO_DEVICE_OUT_SPEAKER;
3625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003626 out->flags = flags;
3627 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003628 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003629 out->format = config->format;
3630 out->sample_rate = config->sample_rate;
3631 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3632 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003633 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634
3635 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003636 if (audio_is_linear_pcm(out->format) &&
3637 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003638 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003639 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003640 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003641 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003642 if (config->sample_rate == 0)
3643 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3644 if (config->channel_mask == 0)
3645 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3646 if (config->format == AUDIO_FORMAT_DEFAULT)
3647 config->format = AUDIO_FORMAT_PCM_16_BIT;
3648 } else if (is_usb_dev) {
3649 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3650 &config->format,
3651 &out->supported_formats[0],
3652 MAX_SUPPORTED_FORMATS,
3653 &config->channel_mask,
3654 &out->supported_channel_masks[0],
3655 MAX_SUPPORTED_CHANNEL_MASKS,
3656 &config->sample_rate,
3657 &out->supported_sample_rates[0],
3658 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003659 ALOGV("plugged dev USB ret %d", ret);
3660 } else {
3661 ret = -1;
3662 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003663 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003664 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003665 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003666
Haynes Mathew George569b7482017-05-08 14:44:27 -07003667 out->channel_mask = config->channel_mask;
3668 out->sample_rate = config->sample_rate;
3669 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003670 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3671 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003672 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003673 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003674 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003675 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3676 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003677 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003678 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003679 pthread_mutex_lock(&adev->lock);
3680 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3681 pthread_mutex_unlock(&adev->lock);
3682
3683 // reject offload during card offline to allow
3684 // fallback to s/w paths
3685 if (offline) {
3686 ret = -ENODEV;
3687 goto error_open;
3688 }
3689
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003690 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3691 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3692 ALOGE("%s: Unsupported Offload information", __func__);
3693 ret = -EINVAL;
3694 goto error_open;
3695 }
3696 if (!is_supported_format(config->offload_info.format)) {
3697 ALOGE("%s: Unsupported audio format", __func__);
3698 ret = -EINVAL;
3699 goto error_open;
3700 }
3701
3702 out->compr_config.codec = (struct snd_codec *)
3703 calloc(1, sizeof(struct snd_codec));
3704
3705 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3706 if (config->offload_info.channel_mask)
3707 out->channel_mask = config->offload_info.channel_mask;
3708 else if (config->channel_mask)
3709 out->channel_mask = config->channel_mask;
3710 out->format = config->offload_info.format;
3711 out->sample_rate = config->offload_info.sample_rate;
3712
3713 out->stream.set_callback = out_set_callback;
3714 out->stream.pause = out_pause;
3715 out->stream.resume = out_resume;
3716 out->stream.drain = out_drain;
3717 out->stream.flush = out_flush;
3718
3719 out->compr_config.codec->id =
3720 get_snd_codec_id(config->offload_info.format);
3721 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3722 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003723 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003724 out->compr_config.codec->bit_rate =
3725 config->offload_info.bit_rate;
3726 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003727 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003728 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3729
3730 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3731 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003732
3733 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003734 create_offload_callback_thread(out);
3735 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3736 __func__, config->offload_info.version,
3737 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003738 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003739 switch (config->sample_rate) {
3740 case 8000:
3741 case 16000:
3742 case 48000:
3743 out->sample_rate = config->sample_rate;
3744 break;
3745 default:
3746 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003747 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003748 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003749 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3750 out->config = pcm_config_afe_proxy_playback;
3751 adev->voice_tx_output = out;
David Lin6b00c232017-07-26 00:20:16 -07003752 } else if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3753 AUDIO_OUTPUT_FLAG_VOIP_RX)) {
vivek mehtaa68fea62017-06-08 19:04:02 -07003754 uint32_t buffer_size, frame_size;
3755 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3756 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3757 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3758 out->config = pcm_config_voip;
3759 out->config.format = pcm_format_from_audio_format(config->format);
3760 out->config.rate = config->sample_rate;
3761 out->config.channels =
3762 audio_channel_count_from_out_mask(config->channel_mask);
3763 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3764 config->sample_rate,
3765 config->format,
3766 out->config.channels,
3767 false /*is_low_latency*/);
3768 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3769 out->config.period_size = buffer_size / frame_size;
3770 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3771 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003773 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3774 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3775 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003776 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3777 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3778 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003779 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3780 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003781 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003782 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003783 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3784 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3785 out->config = pcm_config_mmap_playback;
3786 out->stream.start = out_start;
3787 out->stream.stop = out_stop;
3788 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3789 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003790 } else {
3791 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3792 out->config = pcm_config_low_latency;
3793 }
3794 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003795 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003796 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003797 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003799
3800 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3801 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3802 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3803 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3804 __func__, config->sample_rate, config->format, config->channel_mask);
3805 config->sample_rate = out->sample_rate;
3806 config->format = out->format;
3807 config->channel_mask = out->channel_mask;
3808 ret = -EINVAL;
3809 goto error_open;
3810 }
3811
Andy Hung6fcba9c2014-03-18 11:53:32 -07003812 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3813 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003815 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003816 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003817 adev->primary_output = out;
3818 else {
3819 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003820 ret = -EEXIST;
3821 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003822 }
3823 }
3824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825 /* Check if this usecase is already existing */
3826 pthread_mutex_lock(&adev->lock);
3827 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3828 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003830 ret = -EEXIST;
3831 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832 }
3833 pthread_mutex_unlock(&adev->lock);
3834
3835 out->stream.common.get_sample_rate = out_get_sample_rate;
3836 out->stream.common.set_sample_rate = out_set_sample_rate;
3837 out->stream.common.get_buffer_size = out_get_buffer_size;
3838 out->stream.common.get_channels = out_get_channels;
3839 out->stream.common.get_format = out_get_format;
3840 out->stream.common.set_format = out_set_format;
3841 out->stream.common.standby = out_standby;
3842 out->stream.common.dump = out_dump;
3843 out->stream.common.set_parameters = out_set_parameters;
3844 out->stream.common.get_parameters = out_get_parameters;
3845 out->stream.common.add_audio_effect = out_add_audio_effect;
3846 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3847 out->stream.get_latency = out_get_latency;
3848 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003849#ifdef NO_AUDIO_OUT
3850 out->stream.write = out_write_for_no_output;
3851#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003853#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 out->stream.get_render_position = out_get_render_position;
3855 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003856 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857
Eric Laurent0e46adf2016-12-16 12:49:24 -08003858 if (out->realtime)
3859 out->af_period_multiplier = af_period_multiplier;
3860 else
3861 out->af_period_multiplier = 1;
3862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003864 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003865 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003867 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003868 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003869 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 config->format = out->stream.common.get_format(&out->stream.common);
3872 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3873 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3874
Andy Hunga452b0a2017-03-15 14:51:15 -07003875 out->error_log = error_log_create(
3876 ERROR_LOG_ENTRIES,
3877 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3878
Andy Hungfc044e12017-03-20 09:24:22 -07003879 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003880 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003881 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003882 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3883 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3884
3885 out->power_log = power_log_create(
3886 config->sample_rate,
3887 audio_channel_count_from_out_mask(config->channel_mask),
3888 config->format,
3889 POWER_LOG_ENTRIES,
3890 POWER_LOG_FRAMES_PER_ENTRY);
3891 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003892
3893 /*
3894 By locking output stream before registering, we allow the callback
3895 to update stream's state only after stream's initial state is set to
3896 adev state.
3897 */
3898 lock_output_stream(out);
3899 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3900 pthread_mutex_lock(&adev->lock);
3901 out->card_status = adev->card_status;
3902 pthread_mutex_unlock(&adev->lock);
3903 pthread_mutex_unlock(&out->lock);
3904
vivek mehta4a824772017-06-08 19:05:49 -07003905 stream_app_type_cfg_init(&out->app_type_cfg);
3906
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003908
Eric Laurent994a6932013-07-17 11:51:42 -07003909 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003911
3912error_open:
3913 free(out);
3914 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003915 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003916 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917}
3918
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003919static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920 struct audio_stream_out *stream)
3921{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003922 struct stream_out *out = (struct stream_out *)stream;
3923 struct audio_device *adev = out->dev;
3924
Eric Laurent994a6932013-07-17 11:51:42 -07003925 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003926
3927 // must deregister from sndmonitor first to prevent races
3928 // between the callback and close_stream
3929 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003931 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3932 destroy_offload_callback_thread(out);
3933
3934 if (out->compr_config.codec != NULL)
3935 free(out->compr_config.codec);
3936 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003937
3938 if (adev->voice_tx_output == out)
3939 adev->voice_tx_output = NULL;
3940
Andy Hungfc044e12017-03-20 09:24:22 -07003941 power_log_destroy(out->power_log);
3942 out->power_log = NULL;
3943
Andy Hunga452b0a2017-03-15 14:51:15 -07003944 error_log_destroy(out->error_log);
3945 out->error_log = NULL;
3946
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003947 pthread_cond_destroy(&out->cond);
3948 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003950 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951}
3952
3953static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3954{
3955 struct audio_device *adev = (struct audio_device *)dev;
3956 struct str_parms *parms;
3957 char *str;
3958 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003959 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003960 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003961 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003962
Joe Onorato188b6222016-03-01 11:02:27 -08003963 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003964
3965 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966
3967 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003968 status = voice_set_parameters(adev, parms);
3969 if (status != 0) {
3970 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971 }
3972
3973 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3974 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003975 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003976 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3977 adev->bluetooth_nrec = true;
3978 else
3979 adev->bluetooth_nrec = false;
3980 }
3981
3982 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3983 if (ret >= 0) {
3984 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3985 adev->screen_off = false;
3986 else
3987 adev->screen_off = true;
3988 }
3989
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003990 ret = str_parms_get_int(parms, "rotation", &val);
3991 if (ret >= 0) {
3992 bool reverse_speakers = false;
3993 switch(val) {
3994 // FIXME: note that the code below assumes that the speakers are in the correct placement
3995 // relative to the user when the device is rotated 90deg from its default rotation. This
3996 // assumption is device-specific, not platform-specific like this code.
3997 case 270:
3998 reverse_speakers = true;
3999 break;
4000 case 0:
4001 case 90:
4002 case 180:
4003 break;
4004 default:
4005 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004006 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004007 }
Eric Laurent03f09432014-03-25 18:09:11 -07004008 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004009 // check and set swap
4010 // - check if orientation changed and speaker active
4011 // - set rotation and cache the rotation value
4012 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004013 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004014 }
4015
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004016 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4017 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004018 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004019 }
4020
David Linee3fe402017-03-13 10:00:42 -07004021 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4022 if (ret >= 0) {
4023 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004024 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004025 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4026 if (ret >= 0) {
4027 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004028 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004029 }
Eric Laurent99dab492017-06-17 15:19:08 -07004030 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004031 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4032 if (ret >= 0) {
4033 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004034 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004035 }
4036 }
4037 }
4038
4039 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4040 if (ret >= 0) {
4041 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004042 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004043 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4044 if (ret >= 0) {
4045 const int card = atoi(value);
4046
Eric Laurent99dab492017-06-17 15:19:08 -07004047 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004048 }
Eric Laurent99dab492017-06-17 15:19:08 -07004049 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004050 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4051 if (ret >= 0) {
4052 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004053 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004054 }
4055 }
4056 }
4057
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004058 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004059done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004061 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004062 ALOGV("%s: exit with code(%d)", __func__, status);
4063 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064}
4065
4066static char* adev_get_parameters(const struct audio_hw_device *dev,
4067 const char *keys)
4068{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004069 struct audio_device *adev = (struct audio_device *)dev;
4070 struct str_parms *reply = str_parms_create();
4071 struct str_parms *query = str_parms_create_str(keys);
4072 char *str;
4073
4074 pthread_mutex_lock(&adev->lock);
4075
4076 voice_get_parameters(adev, query, reply);
4077 str = str_parms_to_str(reply);
4078 str_parms_destroy(query);
4079 str_parms_destroy(reply);
4080
4081 pthread_mutex_unlock(&adev->lock);
4082 ALOGV("%s: exit: returns - %s", __func__, str);
4083 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084}
4085
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004086static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087{
4088 return 0;
4089}
4090
Haynes Mathew George5191a852013-09-11 14:19:36 -07004091static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4092{
4093 int ret;
4094 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004095
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004096 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4097
Haynes Mathew George5191a852013-09-11 14:19:36 -07004098 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004099 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004100 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004101
Haynes Mathew George5191a852013-09-11 14:19:36 -07004102 return ret;
4103}
4104
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004105static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106{
4107 return -ENOSYS;
4108}
4109
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004110static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4111 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112{
4113 return -ENOSYS;
4114}
4115
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004116static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004117{
4118 return -ENOSYS;
4119}
4120
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004121static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122{
4123 return -ENOSYS;
4124}
4125
4126static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4127{
4128 struct audio_device *adev = (struct audio_device *)dev;
4129
4130 pthread_mutex_lock(&adev->lock);
4131 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004132 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004134 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4135 voice_is_in_call(adev)) {
4136 voice_stop_call(adev);
4137 adev->current_call_output = NULL;
4138 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139 }
4140 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004141
4142 audio_extn_extspk_set_mode(adev->extspk, mode);
4143
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144 return 0;
4145}
4146
4147static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4148{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004149 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151
Eric Laurent2bafff12016-03-17 12:17:23 -07004152 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004153 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004154 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4155 ret = audio_extn_hfp_set_mic_mute(adev, state);
4156 } else {
4157 ret = voice_set_mic_mute(adev, state);
4158 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004159 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004160 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004161
4162 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163}
4164
4165static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4166{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004167 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168 return 0;
4169}
4170
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004171static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 const struct audio_config *config)
4173{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004174 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004175
Eric Laurent74b55762017-07-09 17:04:53 -07004176 /* Don't know if USB HIFI in this context so use true to be conservative */
4177 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4178 true /*is_usb_hifi */) != 0)
4179 return 0;
4180
vivek mehtaa68fea62017-06-08 19:04:02 -07004181 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4182 config->sample_rate, config->format,
4183 channel_count,
4184 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004185}
4186
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004187static bool adev_input_allow_hifi_record(struct audio_device *adev,
4188 audio_devices_t devices,
4189 audio_input_flags_t flags,
4190 audio_source_t source) {
4191 const bool allowed = true;
4192
4193 if (!audio_is_usb_in_device(devices))
4194 return !allowed;
4195
4196 switch (flags) {
4197 case AUDIO_INPUT_FLAG_NONE:
4198 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4199 break;
4200 default:
4201 return !allowed;
4202 }
4203
4204 switch (source) {
4205 case AUDIO_SOURCE_DEFAULT:
4206 case AUDIO_SOURCE_MIC:
4207 case AUDIO_SOURCE_UNPROCESSED:
4208 break;
4209 default:
4210 return !allowed;
4211 }
4212
4213 switch (adev->mode) {
4214 case 0:
4215 break;
4216 default:
4217 return !allowed;
4218 }
4219
4220 return allowed;
4221}
4222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004224 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004225 audio_devices_t devices,
4226 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004227 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004228 audio_input_flags_t flags,
4229 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004230 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231{
4232 struct audio_device *adev = (struct audio_device *)dev;
4233 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004234 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004235 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004236 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004237 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004238 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4239 devices,
4240 flags,
4241 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004242 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004244
Andy Hungd9653bd2017-08-01 19:31:39 -07004245 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4246 return -ENOSYS;
4247 }
4248
Eric Laurent74b55762017-07-09 17:04:53 -07004249 if (!(is_usb_dev && may_use_hifi_record)) {
4250 if (config->sample_rate == 0)
4251 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4252 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4253 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4254 if (config->format == AUDIO_FORMAT_DEFAULT)
4255 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004256
Eric Laurent74b55762017-07-09 17:04:53 -07004257 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4258
4259 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4260 return -EINVAL;
4261 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004263 if (audio_extn_tfa_98xx_is_supported() &&
4264 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004265 return -EINVAL;
4266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004267 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4268
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004269 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004270 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004272 in->stream.common.get_sample_rate = in_get_sample_rate;
4273 in->stream.common.set_sample_rate = in_set_sample_rate;
4274 in->stream.common.get_buffer_size = in_get_buffer_size;
4275 in->stream.common.get_channels = in_get_channels;
4276 in->stream.common.get_format = in_get_format;
4277 in->stream.common.set_format = in_set_format;
4278 in->stream.common.standby = in_standby;
4279 in->stream.common.dump = in_dump;
4280 in->stream.common.set_parameters = in_set_parameters;
4281 in->stream.common.get_parameters = in_get_parameters;
4282 in->stream.common.add_audio_effect = in_add_audio_effect;
4283 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4284 in->stream.set_gain = in_set_gain;
4285 in->stream.read = in_read;
4286 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004287 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004288
4289 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004290 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004291 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004293 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004294 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004295
Haynes Mathew George569b7482017-05-08 14:44:27 -07004296 if (is_usb_dev && may_use_hifi_record) {
4297 /* HiFi record selects an appropriate format, channel, rate combo
4298 depending on sink capabilities*/
4299 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4300 &config->format,
4301 &in->supported_formats[0],
4302 MAX_SUPPORTED_FORMATS,
4303 &config->channel_mask,
4304 &in->supported_channel_masks[0],
4305 MAX_SUPPORTED_CHANNEL_MASKS,
4306 &config->sample_rate,
4307 &in->supported_sample_rates[0],
4308 MAX_SUPPORTED_SAMPLE_RATES);
4309 if (ret != 0) {
4310 ret = -EINVAL;
4311 goto err_open;
4312 }
Eric Laurent74b55762017-07-09 17:04:53 -07004313 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004314 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004315 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004316 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4317 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4318 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4319 bool ret_error = false;
4320 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4321 from HAL is 8_24
4322 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4323 8_24 return error indicating supported format is 8_24
4324 *> In case of any other source requesting 24 bit or float return error
4325 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004326
vivek mehta57ff9b52016-04-28 14:13:08 -07004327 on error flinger will retry with supported format passed
4328 */
4329 if (source != AUDIO_SOURCE_UNPROCESSED) {
4330 config->format = AUDIO_FORMAT_PCM_16_BIT;
4331 ret_error = true;
4332 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4333 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4334 ret_error = true;
4335 }
4336
4337 if (ret_error) {
4338 ret = -EINVAL;
4339 goto err_open;
4340 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004341 }
4342
vivek mehta57ff9b52016-04-28 14:13:08 -07004343 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004344 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004345
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004347 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4348 if (config->sample_rate == 0)
4349 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4350 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4351 config->sample_rate != 8000) {
4352 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4353 ret = -EINVAL;
4354 goto err_open;
4355 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004356
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004357 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4358 config->format = AUDIO_FORMAT_PCM_16_BIT;
4359 ret = -EINVAL;
4360 goto err_open;
4361 }
4362
4363 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4364 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004365 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004366 } else if (is_usb_dev && may_use_hifi_record) {
4367 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4368 in->config = pcm_config_audio_capture;
4369 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004370 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4371 config->sample_rate,
4372 config->format,
4373 channel_count,
4374 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004375 in->config.period_size = buffer_size / frame_size;
4376 in->config.rate = config->sample_rate;
4377 in->af_period_multiplier = 1;
4378 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004379 } else {
4380 in->usecase = USECASE_AUDIO_RECORD;
4381 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004382 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004383 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004384#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004385 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004386#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004387 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004388 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004389 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004390 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004391 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4392 config->sample_rate,
4393 config->format,
4394 channel_count,
4395 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004396 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004397 in->config.rate = config->sample_rate;
4398 in->af_period_multiplier = 1;
4399 } else {
4400 // period size is left untouched for rt mode playback
4401 in->config = pcm_config_audio_capture_rt;
4402 in->af_period_multiplier = af_period_multiplier;
4403 }
4404 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4405 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004406 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004407 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4408 in->config = pcm_config_mmap_capture;
4409 in->stream.start = in_start;
4410 in->stream.stop = in_stop;
4411 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4412 in->stream.get_mmap_position = in_get_mmap_position;
4413 in->af_period_multiplier = 1;
4414 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004415 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004416 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004417 (config->sample_rate == 8000 ||
4418 config->sample_rate == 16000 ||
4419 config->sample_rate == 32000 ||
4420 config->sample_rate == 48000) &&
4421 channel_count == 1) {
4422 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4423 in->config = pcm_config_audio_capture;
4424 frame_size = audio_stream_in_frame_size(&in->stream);
4425 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4426 config->sample_rate,
4427 config->format,
4428 channel_count, false /*is_low_latency*/);
4429 in->config.period_size = buffer_size / frame_size;
4430 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4431 in->config.rate = config->sample_rate;
4432 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004433 } else {
4434 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004435 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004436 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4437 config->sample_rate,
4438 config->format,
4439 channel_count,
4440 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004441 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004442 in->config.rate = config->sample_rate;
4443 in->af_period_multiplier = 1;
4444 }
4445 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4446 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004447 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004448
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004449 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004450 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004451
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004452 /* This stream could be for sound trigger lab,
4453 get sound trigger pcm if present */
4454 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004455
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004456 lock_input_stream(in);
4457 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4458 pthread_mutex_lock(&adev->lock);
4459 in->card_status = adev->card_status;
4460 pthread_mutex_unlock(&adev->lock);
4461 pthread_mutex_unlock(&in->lock);
4462
vivek mehta4a824772017-06-08 19:05:49 -07004463 stream_app_type_cfg_init(&in->app_type_cfg);
4464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004465 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004466 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004467 return 0;
4468
4469err_open:
4470 free(in);
4471 *stream_in = NULL;
4472 return ret;
4473}
4474
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004475static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004476 struct audio_stream_in *stream)
4477{
Eric Laurent994a6932013-07-17 11:51:42 -07004478 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004479
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004480 // must deregister from sndmonitor first to prevent races
4481 // between the callback and close_stream
4482 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483 in_standby(&stream->common);
4484 free(stream);
4485
4486 return;
4487}
4488
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004489static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004490{
4491 return 0;
4492}
4493
Andy Hung31aca912014-03-20 17:14:59 -07004494/* verifies input and output devices and their capabilities.
4495 *
4496 * This verification is required when enabling extended bit-depth or
4497 * sampling rates, as not all qcom products support it.
4498 *
4499 * Suitable for calling only on initialization such as adev_open().
4500 * It fills the audio_device use_case_table[] array.
4501 *
4502 * Has a side-effect that it needs to configure audio routing / devices
4503 * in order to power up the devices and read the device parameters.
4504 * It does not acquire any hw device lock. Should restore the devices
4505 * back to "normal state" upon completion.
4506 */
4507static int adev_verify_devices(struct audio_device *adev)
4508{
4509 /* enumeration is a bit difficult because one really wants to pull
4510 * the use_case, device id, etc from the hidden pcm_device_table[].
4511 * In this case there are the following use cases and device ids.
4512 *
4513 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4514 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004515 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004516 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4517 * [USECASE_AUDIO_RECORD] = {0, 0},
4518 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4519 * [USECASE_VOICE_CALL] = {2, 2},
4520 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004521 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004522 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4523 */
4524
4525 /* should be the usecases enabled in adev_open_input_stream() */
4526 static const int test_in_usecases[] = {
4527 USECASE_AUDIO_RECORD,
4528 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4529 };
4530 /* should be the usecases enabled in adev_open_output_stream()*/
4531 static const int test_out_usecases[] = {
4532 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4533 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4534 };
4535 static const usecase_type_t usecase_type_by_dir[] = {
4536 PCM_PLAYBACK,
4537 PCM_CAPTURE,
4538 };
4539 static const unsigned flags_by_dir[] = {
4540 PCM_OUT,
4541 PCM_IN,
4542 };
4543
4544 size_t i;
4545 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004546 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004547 char info[512]; /* for possible debug info */
4548
4549 for (dir = 0; dir < 2; ++dir) {
4550 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4551 const unsigned flags_dir = flags_by_dir[dir];
4552 const size_t testsize =
4553 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4554 const int *testcases =
4555 dir ? test_in_usecases : test_out_usecases;
4556 const audio_devices_t audio_device =
4557 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4558
4559 for (i = 0; i < testsize; ++i) {
4560 const audio_usecase_t audio_usecase = testcases[i];
4561 int device_id;
4562 snd_device_t snd_device;
4563 struct pcm_params **pparams;
4564 struct stream_out out;
4565 struct stream_in in;
4566 struct audio_usecase uc_info;
4567 int retval;
4568
4569 pparams = &adev->use_case_table[audio_usecase];
4570 pcm_params_free(*pparams); /* can accept null input */
4571 *pparams = NULL;
4572
4573 /* find the device ID for the use case (signed, for error) */
4574 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4575 if (device_id < 0)
4576 continue;
4577
4578 /* prepare structures for device probing */
4579 memset(&uc_info, 0, sizeof(uc_info));
4580 uc_info.id = audio_usecase;
4581 uc_info.type = usecase_type;
4582 if (dir) {
4583 adev->active_input = &in;
4584 memset(&in, 0, sizeof(in));
4585 in.device = audio_device;
4586 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4587 uc_info.stream.in = &in;
4588 } else {
4589 adev->active_input = NULL;
4590 }
4591 memset(&out, 0, sizeof(out));
4592 out.devices = audio_device; /* only field needed in select_devices */
4593 uc_info.stream.out = &out;
4594 uc_info.devices = audio_device;
4595 uc_info.in_snd_device = SND_DEVICE_NONE;
4596 uc_info.out_snd_device = SND_DEVICE_NONE;
4597 list_add_tail(&adev->usecase_list, &uc_info.list);
4598
4599 /* select device - similar to start_(in/out)put_stream() */
4600 retval = select_devices(adev, audio_usecase);
4601 if (retval >= 0) {
4602 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4603#if LOG_NDEBUG == 0
4604 if (*pparams) {
4605 ALOGV("%s: (%s) card %d device %d", __func__,
4606 dir ? "input" : "output", card_id, device_id);
4607 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004608 } else {
4609 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4610 }
4611#endif
4612 }
4613
4614 /* deselect device - similar to stop_(in/out)put_stream() */
4615 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004616 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004617 /* 2. Disable the rx device */
4618 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004619 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004620 list_remove(&uc_info.list);
4621 }
4622 }
4623 adev->active_input = NULL; /* restore adev state */
4624 return 0;
4625}
4626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004627static int adev_close(hw_device_t *device)
4628{
Andy Hung31aca912014-03-20 17:14:59 -07004629 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004631
4632 if (!adev)
4633 return 0;
4634
4635 pthread_mutex_lock(&adev_init_lock);
4636
4637 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004638 audio_extn_snd_mon_unregister_listener(adev);
4639 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004640 audio_route_free(adev->audio_route);
4641 free(adev->snd_dev_ref_cnt);
4642 platform_deinit(adev->platform);
4643 audio_extn_extspk_deinit(adev->extspk);
4644 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004645 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004646 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4647 pcm_params_free(adev->use_case_table[i]);
4648 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004649 if (adev->adm_deinit)
4650 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004651 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004652 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004653
4654 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656 return 0;
4657}
4658
Glenn Kasten4f993392014-05-14 07:30:48 -07004659/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4660 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4661 * just that it _might_ work.
4662 */
4663static int period_size_is_plausible_for_low_latency(int period_size)
4664{
4665 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004666 case 48:
4667 case 96:
4668 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004669 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004670 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004671 case 240:
4672 case 320:
4673 case 480:
4674 return 1;
4675 default:
4676 return 0;
4677 }
4678}
4679
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004680static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4681{
4682 int card;
4683 card_status_t status;
4684
4685 if (!parms)
4686 return;
4687
4688 if (parse_snd_card_status(parms, &card, &status) < 0)
4689 return;
4690
4691 pthread_mutex_lock(&adev->lock);
4692 bool valid_cb = (card == adev->snd_card);
4693 if (valid_cb) {
4694 if (adev->card_status != status) {
4695 adev->card_status = status;
4696 platform_snd_card_update(adev->platform, status);
4697 }
4698 }
4699 pthread_mutex_unlock(&adev->lock);
4700 return;
4701}
4702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004703static int adev_open(const hw_module_t *module, const char *name,
4704 hw_device_t **device)
4705{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004706 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004707
Eric Laurent2bafff12016-03-17 12:17:23 -07004708 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004710 pthread_mutex_lock(&adev_init_lock);
4711 if (audio_device_ref_count != 0) {
4712 *device = &adev->device.common;
4713 audio_device_ref_count++;
4714 ALOGV("%s: returning existing instance of adev", __func__);
4715 ALOGV("%s: exit", __func__);
4716 pthread_mutex_unlock(&adev_init_lock);
4717 return 0;
4718 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004719 adev = calloc(1, sizeof(struct audio_device));
4720
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004721 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4724 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4725 adev->device.common.module = (struct hw_module_t *)module;
4726 adev->device.common.close = adev_close;
4727
4728 adev->device.init_check = adev_init_check;
4729 adev->device.set_voice_volume = adev_set_voice_volume;
4730 adev->device.set_master_volume = adev_set_master_volume;
4731 adev->device.get_master_volume = adev_get_master_volume;
4732 adev->device.set_master_mute = adev_set_master_mute;
4733 adev->device.get_master_mute = adev_get_master_mute;
4734 adev->device.set_mode = adev_set_mode;
4735 adev->device.set_mic_mute = adev_set_mic_mute;
4736 adev->device.get_mic_mute = adev_get_mic_mute;
4737 adev->device.set_parameters = adev_set_parameters;
4738 adev->device.get_parameters = adev_get_parameters;
4739 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4740 adev->device.open_output_stream = adev_open_output_stream;
4741 adev->device.close_output_stream = adev_close_output_stream;
4742 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004744 adev->device.close_input_stream = adev_close_input_stream;
4745 adev->device.dump = adev_dump;
4746
4747 /* Set the default route before the PCM stream is opened */
4748 pthread_mutex_lock(&adev->lock);
4749 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004750 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004751 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004752 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004753 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004754 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004755 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004756 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004757 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758 pthread_mutex_unlock(&adev->lock);
4759
4760 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004761 adev->platform = platform_init(adev);
4762 if (!adev->platform) {
4763 free(adev->snd_dev_ref_cnt);
4764 free(adev);
4765 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4766 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004767 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004768 return -EINVAL;
4769 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004770 adev->extspk = audio_extn_extspk_init(adev);
4771
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004772 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4773 if (adev->visualizer_lib == NULL) {
4774 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4775 } else {
4776 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4777 adev->visualizer_start_output =
4778 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4779 "visualizer_hal_start_output");
4780 adev->visualizer_stop_output =
4781 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4782 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004783 }
4784
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004785 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4786 if (adev->offload_effects_lib == NULL) {
4787 ALOGW("%s: DLOPEN failed for %s", __func__,
4788 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4789 } else {
4790 ALOGV("%s: DLOPEN successful for %s", __func__,
4791 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4792 adev->offload_effects_start_output =
4793 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4794 "offload_effects_bundle_hal_start_output");
4795 adev->offload_effects_stop_output =
4796 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4797 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004798 }
4799
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004800 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4801 if (adev->adm_lib == NULL) {
4802 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4803 } else {
4804 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4805 adev->adm_init = (adm_init_t)
4806 dlsym(adev->adm_lib, "adm_init");
4807 adev->adm_deinit = (adm_deinit_t)
4808 dlsym(adev->adm_lib, "adm_deinit");
4809 adev->adm_register_input_stream = (adm_register_input_stream_t)
4810 dlsym(adev->adm_lib, "adm_register_input_stream");
4811 adev->adm_register_output_stream = (adm_register_output_stream_t)
4812 dlsym(adev->adm_lib, "adm_register_output_stream");
4813 adev->adm_deregister_stream = (adm_deregister_stream_t)
4814 dlsym(adev->adm_lib, "adm_deregister_stream");
4815 adev->adm_request_focus = (adm_request_focus_t)
4816 dlsym(adev->adm_lib, "adm_request_focus");
4817 adev->adm_abandon_focus = (adm_abandon_focus_t)
4818 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004819 adev->adm_set_config = (adm_set_config_t)
4820 dlsym(adev->adm_lib, "adm_set_config");
4821 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4822 dlsym(adev->adm_lib, "adm_request_focus_v2");
4823 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4824 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4825 adev->adm_on_routing_change = (adm_on_routing_change_t)
4826 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004827 }
4828
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004829 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004830 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004832 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004833
Andy Hung31aca912014-03-20 17:14:59 -07004834 if (k_enable_extended_precision)
4835 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004836
Glenn Kasten4f993392014-05-14 07:30:48 -07004837 char value[PROPERTY_VALUE_MAX];
4838 int trial;
4839 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4840 trial = atoi(value);
4841 if (period_size_is_plausible_for_low_latency(trial)) {
4842 pcm_config_low_latency.period_size = trial;
4843 pcm_config_low_latency.start_threshold = trial / 4;
4844 pcm_config_low_latency.avail_min = trial / 4;
4845 configured_low_latency_capture_period_size = trial;
4846 }
4847 }
4848 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4849 trial = atoi(value);
4850 if (period_size_is_plausible_for_low_latency(trial)) {
4851 configured_low_latency_capture_period_size = trial;
4852 }
4853 }
4854
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004855 // commented as full set of app type cfg is sent from platform
4856 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004857 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004858
4859 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4860 af_period_multiplier = atoi(value);
4861 if (af_period_multiplier < 0) {
4862 af_period_multiplier = 2;
4863 } else if (af_period_multiplier > 4) {
4864 af_period_multiplier = 4;
4865 }
4866 ALOGV("new period_multiplier = %d", af_period_multiplier);
4867 }
4868
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004869 audio_extn_tfa_98xx_init(adev);
4870
vivek mehta1a9b7c02015-06-25 11:49:38 -07004871 pthread_mutex_unlock(&adev_init_lock);
4872
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004873 if (adev->adm_init)
4874 adev->adm_data = adev->adm_init();
4875
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004876 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004877 audio_extn_snd_mon_init();
4878 pthread_mutex_lock(&adev->lock);
4879 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4880 adev->card_status = CARD_STATUS_ONLINE;
4881 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004882 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004883
Eric Laurent2bafff12016-03-17 12:17:23 -07004884 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885 return 0;
4886}
4887
4888static struct hw_module_methods_t hal_module_methods = {
4889 .open = adev_open,
4890};
4891
4892struct audio_module HAL_MODULE_INFO_SYM = {
4893 .common = {
4894 .tag = HARDWARE_MODULE_TAG,
4895 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4896 .hal_api_version = HARDWARE_HAL_API_VERSION,
4897 .id = AUDIO_HARDWARE_MODULE_ID,
4898 .name = "QCOM Audio HAL",
4899 .author = "Code Aurora Forum",
4900 .methods = &hal_module_methods,
4901 },
4902};