blob: 38e8c36d6817d91b756b75460d756d738b71faa3 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070054#include "platform_api.h"
55#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070056#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080059#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060
Eric Laurent397db572016-05-11 11:31:47 -070061/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
62 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070063#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070064// 2 buffers causes problems with high bitrate files
65#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066/* ToDo: Check and update a proper value in msec */
67#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070068/* treat as unsigned Q1.13 */
69#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070070#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070071
72/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070073#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070074
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070075#define PROXY_OPEN_RETRY_COUNT 100
76#define PROXY_OPEN_WAIT_TIME 20
77
vivek mehtadae44712015-07-27 14:13:18 -070078#define MIN_CHANNEL_COUNT 1
79#define DEFAULT_CHANNEL_COUNT 2
80
Jean-Michel Trivic0750692015-10-12 12:12:32 -070081#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
82#define MAX_CHANNEL_COUNT 1
83#else
vivek mehtadae44712015-07-27 14:13:18 -070084#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
85#define XSTR(x) STR(x)
86#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#endif
Eric Laurent74b55762017-07-09 17:04:53 -070088#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070089
Haynes Mathew George03c40102016-01-29 17:57:48 -080090#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
91
Glenn Kasten4f993392014-05-14 07:30:48 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurent0e46adf2016-12-16 12:49:24 -080095
96#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080097#define MMAP_PERIOD_COUNT_MIN 32
98#define MMAP_PERIOD_COUNT_MAX 512
99#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800100
Andy Hungd13f0d32017-06-12 13:58:37 -0700101static const int64_t NANOS_PER_SECOND = 1000000000;
Eric Laurent0e46adf2016-12-16 12:49:24 -0800102
Andy Hung31aca912014-03-20 17:14:59 -0700103/* This constant enables extended precision handling.
104 * TODO The flag is off until more testing is done.
105 */
106static const bool k_enable_extended_precision = false;
107
Eric Laurentb23d5282013-05-14 15:27:20 -0700108struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700109 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700110 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
111 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
112 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
113 .format = PCM_FORMAT_S16_LE,
114 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
115 .stop_threshold = INT_MAX,
116 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
117};
118
119struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700120 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700121 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
122 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
123 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
124 .format = PCM_FORMAT_S16_LE,
125 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
126 .stop_threshold = INT_MAX,
127 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
128};
129
Haynes Mathew George03c40102016-01-29 17:57:48 -0800130static int af_period_multiplier = 4;
131struct pcm_config pcm_config_rt = {
132 .channels = DEFAULT_CHANNEL_COUNT,
133 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
134 .period_size = ULL_PERIOD_SIZE, //1 ms
135 .period_count = 512, //=> buffer size is 512ms
136 .format = PCM_FORMAT_S16_LE,
137 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
138 .stop_threshold = INT_MAX,
139 .silence_threshold = 0,
140 .silence_size = 0,
141 .avail_min = ULL_PERIOD_SIZE, //1 ms
142};
143
Eric Laurentb23d5282013-05-14 15:27:20 -0700144struct pcm_config pcm_config_hdmi_multi = {
145 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
146 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
147 .period_size = HDMI_MULTI_PERIOD_SIZE,
148 .period_count = HDMI_MULTI_PERIOD_COUNT,
149 .format = PCM_FORMAT_S16_LE,
150 .start_threshold = 0,
151 .stop_threshold = INT_MAX,
152 .avail_min = 0,
153};
154
Eric Laurent0e46adf2016-12-16 12:49:24 -0800155struct pcm_config pcm_config_mmap_playback = {
156 .channels = DEFAULT_CHANNEL_COUNT,
157 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
158 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800159 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800160 .format = PCM_FORMAT_S16_LE,
161 .start_threshold = MMAP_PERIOD_SIZE*8,
162 .stop_threshold = INT32_MAX,
163 .silence_threshold = 0,
164 .silence_size = 0,
165 .avail_min = MMAP_PERIOD_SIZE, //1 ms
166};
167
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800168struct pcm_config pcm_config_hifi = {
169 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
171 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
172 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
173 .format = PCM_FORMAT_S24_3LE,
174 .start_threshold = 0,
175 .stop_threshold = INT_MAX,
176 .avail_min = 0,
177};
178
Eric Laurentb23d5282013-05-14 15:27:20 -0700179struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700180 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
182 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700183 .stop_threshold = INT_MAX,
184 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185};
186
Haynes Mathew George03c40102016-01-29 17:57:48 -0800187struct pcm_config pcm_config_audio_capture_rt = {
188 .channels = DEFAULT_CHANNEL_COUNT,
189 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
190 .period_size = ULL_PERIOD_SIZE,
191 .period_count = 512,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = 0,
194 .stop_threshold = INT_MAX,
195 .silence_threshold = 0,
196 .silence_size = 0,
197 .avail_min = ULL_PERIOD_SIZE, //1 ms
198};
199
Eric Laurent0e46adf2016-12-16 12:49:24 -0800200struct pcm_config pcm_config_mmap_capture = {
201 .channels = DEFAULT_CHANNEL_COUNT,
202 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
203 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800204 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800205 .format = PCM_FORMAT_S16_LE,
206 .start_threshold = 0,
207 .stop_threshold = INT_MAX,
208 .silence_threshold = 0,
209 .silence_size = 0,
210 .avail_min = MMAP_PERIOD_SIZE, //1 ms
211};
212
vivek mehtaa68fea62017-06-08 19:04:02 -0700213struct pcm_config pcm_config_voip = {
214 .channels = 1,
215 .period_count = 2,
216 .format = PCM_FORMAT_S16_LE,
217 .stop_threshold = INT_MAX,
218 .avail_min = 0,
219};
220
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700221#define AFE_PROXY_CHANNEL_COUNT 2
222#define AFE_PROXY_SAMPLING_RATE 48000
223
224#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
225#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
226
227struct pcm_config pcm_config_afe_proxy_playback = {
228 .channels = AFE_PROXY_CHANNEL_COUNT,
229 .rate = AFE_PROXY_SAMPLING_RATE,
230 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
231 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234 .stop_threshold = INT_MAX,
235 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
236};
237
238#define AFE_PROXY_RECORD_PERIOD_SIZE 768
239#define AFE_PROXY_RECORD_PERIOD_COUNT 4
240
241struct pcm_config pcm_config_afe_proxy_record = {
242 .channels = AFE_PROXY_CHANNEL_COUNT,
243 .rate = AFE_PROXY_SAMPLING_RATE,
244 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
245 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
246 .format = PCM_FORMAT_S16_LE,
247 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
248 .stop_threshold = INT_MAX,
249 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
250};
251
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700252const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700253 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
254 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800255 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700257 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700258 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800259 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260
Eric Laurentb23d5282013-05-14 15:27:20 -0700261 [USECASE_AUDIO_RECORD] = "audio-record",
262 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700264 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700265
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800266 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
267 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700268
Eric Laurentb23d5282013-05-14 15:27:20 -0700269 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700270 [USECASE_VOICE2_CALL] = "voice2-call",
271 [USECASE_VOLTE_CALL] = "volte-call",
272 [USECASE_QCHAT_CALL] = "qchat-call",
273 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800274 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
275 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700276
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700277 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
278 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
279
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
281 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700282
283 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
284 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
285 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
286
vivek mehtaa68fea62017-06-08 19:04:02 -0700287 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
288 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Eric Laurentb23d5282013-05-14 15:27:20 -0700289};
290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291
292#define STRING_TO_ENUM(string) { #string, string }
293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800294struct string_to_enum {
295 const char *name;
296 uint32_t value;
297};
298
Haynes Mathew George569b7482017-05-08 14:44:27 -0700299static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800300 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
301 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
302 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700303 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700304 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700305 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
306 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
307 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
308 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
309 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
310 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
311 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
312 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800314};
315
Haynes Mathew George5191a852013-09-11 14:19:36 -0700316static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700317static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700318static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700319static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700322
Haynes Mathew George03c40102016-01-29 17:57:48 -0800323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
348 return;
349
350 if (!adev->adm_register_output_stream)
351 return;
352
353 adev->adm_register_output_stream(adev->adm_data,
354 out->handle,
355 out->flags);
356
357 if (!adev->adm_set_config)
358 return;
359
360 if (out->realtime) {
361 adev->adm_set_config(adev->adm_data,
362 out->handle,
363 out->pcm, &out->config);
364 }
365}
366
367static void register_in_stream(struct stream_in *in)
368{
369 struct audio_device *adev = in->dev;
370 if (!adev->adm_register_input_stream)
371 return;
372
373 adev->adm_register_input_stream(adev->adm_data,
374 in->capture_handle,
375 in->flags);
376
377 if (!adev->adm_set_config)
378 return;
379
380 if (in->realtime) {
381 adev->adm_set_config(adev->adm_data,
382 in->capture_handle,
383 in->pcm,
384 &in->config);
385 }
386}
387
388static void request_out_focus(struct stream_out *out, long ns)
389{
390 struct audio_device *adev = out->dev;
391
Haynes Mathew George03c40102016-01-29 17:57:48 -0800392 if (adev->adm_request_focus_v2) {
393 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
394 } else if (adev->adm_request_focus) {
395 adev->adm_request_focus(adev->adm_data, out->handle);
396 }
397}
398
399static void request_in_focus(struct stream_in *in, long ns)
400{
401 struct audio_device *adev = in->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, in->capture_handle);
407 }
408}
409
410static void release_out_focus(struct stream_out *out, long ns __unused)
411{
412 struct audio_device *adev = out->dev;
413
414 if (adev->adm_abandon_focus)
415 adev->adm_abandon_focus(adev->adm_data, out->handle);
416}
417
418static void release_in_focus(struct stream_in *in, long ns __unused)
419{
420 struct audio_device *adev = in->dev;
421 if (adev->adm_abandon_focus)
422 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
423}
424
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700425static int parse_snd_card_status(struct str_parms * parms, int * card,
426 card_status_t * status)
427{
428 char value[32]={0};
429 char state[32]={0};
430
431 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
432
433 if (ret < 0)
434 return -1;
435
436 // sscanf should be okay as value is of max length 32.
437 // same as sizeof state.
438 if (sscanf(value, "%d,%s", card, state) < 2)
439 return -1;
440
441 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
442 CARD_STATUS_OFFLINE;
443 return 0;
444}
445
vivek mehta40125092017-08-21 18:48:51 -0700446// always call with adev lock held
447void send_gain_dep_calibration_l() {
448 if (last_known_cal_step >= 0)
449 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
450}
451
vivek mehta1a9b7c02015-06-25 11:49:38 -0700452__attribute__ ((visibility ("default")))
453bool audio_hw_send_gain_dep_calibration(int level) {
454 bool ret_val = false;
455 ALOGV("%s: enter ... ", __func__);
456
457 pthread_mutex_lock(&adev_init_lock);
458
459 if (adev != NULL && adev->platform != NULL) {
460 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700461 last_known_cal_step = level;
462 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463 pthread_mutex_unlock(&adev->lock);
464 } else {
465 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
466 }
467
468 pthread_mutex_unlock(&adev_init_lock);
469
470 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
471 return ret_val;
472}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700473
vivek mehtaa8d7c922016-05-25 14:40:44 -0700474__attribute__ ((visibility ("default")))
475int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
476 int table_size) {
477 int ret_val = 0;
478 ALOGV("%s: enter ... ", __func__);
479
480 pthread_mutex_lock(&adev_init_lock);
481 if (adev == NULL) {
482 ALOGW("%s: adev is NULL .... ", __func__);
483 goto done;
484 }
485
486 pthread_mutex_lock(&adev->lock);
487 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
488 pthread_mutex_unlock(&adev->lock);
489done:
490 pthread_mutex_unlock(&adev_init_lock);
491 ALOGV("%s: exit ... ", __func__);
492 return ret_val;
493}
494
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700495static bool is_supported_format(audio_format_t format)
496{
Eric Laurent8251ac82014-07-23 11:00:25 -0700497 switch (format) {
498 case AUDIO_FORMAT_MP3:
499 case AUDIO_FORMAT_AAC_LC:
500 case AUDIO_FORMAT_AAC_HE_V1:
501 case AUDIO_FORMAT_AAC_HE_V2:
502 return true;
503 default:
504 break;
505 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700506 return false;
507}
508
Haynes Mathew George03c40102016-01-29 17:57:48 -0800509static inline bool is_mmap_usecase(audio_usecase_t uc_id)
510{
511 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
512 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
513}
514
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700515static int get_snd_codec_id(audio_format_t format)
516{
517 int id = 0;
518
Eric Laurent8251ac82014-07-23 11:00:25 -0700519 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700520 case AUDIO_FORMAT_MP3:
521 id = SND_AUDIOCODEC_MP3;
522 break;
523 case AUDIO_FORMAT_AAC:
524 id = SND_AUDIOCODEC_AAC;
525 break;
526 default:
527 ALOGE("%s: Unsupported audio format", __func__);
528 }
529
530 return id;
531}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800532
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800533static int audio_ssr_status(struct audio_device *adev)
534{
535 int ret = 0;
536 struct mixer_ctl *ctl;
537 const char *mixer_ctl_name = "Audio SSR Status";
538
539 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
540 ret = mixer_ctl_get_value(ctl, 0);
541 ALOGD("%s: value: %d", __func__, ret);
542 return ret;
543}
544
vivek mehta4a824772017-06-08 19:05:49 -0700545static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
546{
547 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
548}
549
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800550int enable_audio_route(struct audio_device *adev,
551 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700553 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800555
556 if (usecase == NULL)
557 return -EINVAL;
558
559 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
560
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800561 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800563 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700564 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800565
Yamit Mehtae3b99562016-09-16 22:44:00 +0530566 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800567 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800568 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500569 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700570 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700571 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800573 ALOGV("%s: exit", __func__);
574 return 0;
575}
576
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800577int disable_audio_route(struct audio_device *adev,
578 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700580 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800581 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800582
583 if (usecase == NULL)
584 return -EINVAL;
585
586 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587 if (usecase->type == PCM_CAPTURE)
588 snd_device = usecase->in_snd_device;
589 else
590 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800591 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500592 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700593 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700594 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800596 ALOGV("%s: exit", __func__);
597 return 0;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700601 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700603 int i, num_devices = 0;
604 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800605 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800606 if (snd_device < SND_DEVICE_MIN ||
607 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800608 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800609 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800610 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700612 platform_send_audio_calibration(adev->platform, snd_device);
613
vivek mehtade4849c2016-03-03 17:23:38 -0800614 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700615 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700616 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800617 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700618 }
619
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700620 /* due to the possibility of calibration overwrite between listen
621 and audio, notify sound trigger hal before audio calibration is sent */
622 audio_extn_sound_trigger_update_device_status(snd_device,
623 ST_EVENT_SND_DEVICE_BUSY);
624
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700625 if (audio_extn_spkr_prot_is_enabled())
626 audio_extn_spkr_prot_calib_cancel(adev);
627
zhaoyang yin4211fad2015-06-04 21:13:25 +0800628 audio_extn_dsm_feedback_enable(adev, snd_device, true);
629
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700630 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
631 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
632 audio_extn_spkr_prot_is_enabled()) {
633 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800634 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700635 }
636 if (audio_extn_spkr_prot_start_processing(snd_device)) {
637 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800638 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700639 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700640 } else if (platform_can_split_snd_device(snd_device,
641 &num_devices,
642 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700643 for (i = 0; i < num_devices; i++) {
644 enable_snd_device(adev, new_snd_devices[i]);
645 }
vivek mehtab6506412015-08-07 16:55:17 -0700646 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700647 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800648 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
649 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
650 ALOGE(" %s: Invalid sound device returned", __func__);
651 goto on_error;
652 }
Ed Tam70b5c142016-03-21 19:14:29 -0700653
Eric Laurent2e140aa2016-06-30 17:14:46 -0700654 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800655 audio_route_apply_and_update_path(adev->audio_route, device_name);
656 }
657on_success:
658 adev->snd_dev_ref_cnt[snd_device]++;
659 ret_val = 0;
660on_error:
661 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800662}
663
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800664int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700665 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800666{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700667 int i, num_devices = 0;
668 snd_device_t new_snd_devices[2];
669
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800670 if (snd_device < SND_DEVICE_MIN ||
671 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800672 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800673 return -EINVAL;
674 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
676 ALOGE("%s: device ref cnt is already 0", __func__);
677 return -EINVAL;
678 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800679 audio_extn_tfa_98xx_disable_speaker(snd_device);
680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 adev->snd_dev_ref_cnt[snd_device]--;
682 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800683 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700685 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700686 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
687 audio_extn_spkr_prot_is_enabled()) {
688 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700689
690 // when speaker device is disabled, reset swap.
691 // will be renabled on usecase start
692 platform_set_swap_channels(adev, false);
693
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700694 } else if (platform_can_split_snd_device(snd_device,
695 &num_devices,
696 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700697 for (i = 0; i < num_devices; i++) {
698 disable_snd_device(adev, new_snd_devices[i]);
699 }
vivek mehtab6506412015-08-07 16:55:17 -0700700 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700701 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800702 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
703 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
704 ALOGE(" %s: Invalid sound device returned", __func__);
705 return -EINVAL;
706 }
707
Eric Laurent2e140aa2016-06-30 17:14:46 -0700708 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800709 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700710 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700711 audio_extn_sound_trigger_update_device_status(snd_device,
712 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 }
vivek mehtab6506412015-08-07 16:55:17 -0700714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800715 return 0;
716}
717
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700718/*
719 legend:
720 uc - existing usecase
721 new_uc - new usecase
722 d1, d11, d2 - SND_DEVICE enums
723 a1, a2 - corresponding ANDROID device enums
724 B, B1, B2 - backend strings
725
726case 1
727 uc->dev d1 (a1) B1
728 new_uc->dev d1 (a1), d2 (a2) B1, B2
729
730 resolution: disable and enable uc->dev on d1
731
732case 2
733 uc->dev d1 (a1) B1
734 new_uc->dev d11 (a1) B1
735
736 resolution: need to switch uc since d1 and d11 are related
737 (e.g. speaker and voice-speaker)
738 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
739
740case 3
741 uc->dev d1 (a1) B1
742 new_uc->dev d2 (a2) B2
743
744 resolution: no need to switch uc
745
746case 4
747 uc->dev d1 (a1) B
748 new_uc->dev d2 (a2) B
749
750 resolution: disable enable uc-dev on d2 since backends match
751 we cannot enable two streams on two different devices if they
752 share the same backend. e.g. if offload is on speaker device using
753 QUAD_MI2S backend and a low-latency stream is started on voice-handset
754 using the same backend, offload must also be switched to voice-handset.
755
756case 5
757 uc->dev d1 (a1) B
758 new_uc->dev d1 (a1), d2 (a2) B
759
760 resolution: disable enable uc-dev on d2 since backends match
761 we cannot enable two streams on two different devices if they
762 share the same backend.
763
764case 6
765 uc->dev d1 a1 B1
766 new_uc->dev d2 a1 B2
767
768 resolution: no need to switch
769
770case 7
771
772 uc->dev d1 (a1), d2 (a2) B1, B2
773 new_uc->dev d1 B1
774
775 resolution: no need to switch
776
777*/
778static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
779 struct audio_usecase *new_uc,
780 snd_device_t new_snd_device)
781{
782 audio_devices_t a1 = uc->stream.out->devices;
783 audio_devices_t a2 = new_uc->stream.out->devices;
784
785 snd_device_t d1 = uc->out_snd_device;
786 snd_device_t d2 = new_snd_device;
787
788 // Treat as a special case when a1 and a2 are not disjoint
789 if ((a1 != a2) && (a1 & a2)) {
790 snd_device_t d3[2];
791 int num_devices = 0;
792 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
793 &num_devices,
794 d3);
795 if (ret < 0) {
796 if (ret != -ENOSYS) {
797 ALOGW("%s failed to split snd_device %d",
798 __func__,
799 popcount(a1) > 1 ? d1 : d2);
800 }
801 goto end;
802 }
803
804 // NB: case 7 is hypothetical and isn't a practical usecase yet.
805 // But if it does happen, we need to give priority to d2 if
806 // the combo devices active on the existing usecase share a backend.
807 // This is because we cannot have a usecase active on a combo device
808 // and a new usecase requests one device in this combo pair.
809 if (platform_check_backends_match(d3[0], d3[1])) {
810 return d2; // case 5
811 } else {
812 return d1; // case 1
813 }
814 } else {
815 if (platform_check_backends_match(d1, d2)) {
816 return d2; // case 2, 4
817 } else {
818 return d1; // case 6, 3
819 }
820 }
821
822end:
823 return d2; // return whatever was calculated before.
824}
825
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700826static void check_and_route_playback_usecases(struct audio_device *adev,
827 struct audio_usecase *uc_info,
828 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700829{
830 struct listnode *node;
831 struct audio_usecase *usecase;
832 bool switch_device[AUDIO_USECASE_MAX];
833 int i, num_uc_to_switch = 0;
834
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700835 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
836 uc_info,
837 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700838
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700839 /*
840 * This function is to make sure that all the usecases that are active on
841 * the hardware codec backend are always routed to any one device that is
842 * handled by the hardware codec.
843 * For example, if low-latency and deep-buffer usecases are currently active
844 * on speaker and out_set_parameters(headset) is received on low-latency
845 * output, then we have to make sure deep-buffer is also switched to headset,
846 * because of the limitation that both the devices cannot be enabled
847 * at the same time as they share the same backend.
848 */
849 /* Disable all the usecases on the shared backend other than the
850 specified usecase */
851 for (i = 0; i < AUDIO_USECASE_MAX; i++)
852 switch_device[i] = false;
853
854 list_for_each(node, &adev->usecase_list) {
855 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700856 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
857 continue;
858
859 if (force_routing ||
860 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700861 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
862 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700863 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
865 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700866 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700867 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700868 switch_device[usecase->id] = true;
869 num_uc_to_switch++;
870 }
871 }
872
873 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 list_for_each(node, &adev->usecase_list) {
875 usecase = node_to_item(node, struct audio_usecase, list);
876 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700877 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900878 }
879 }
880
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700881 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900882 list_for_each(node, &adev->usecase_list) {
883 usecase = node_to_item(node, struct audio_usecase, list);
884 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700885 d_device = derive_playback_snd_device(usecase, uc_info,
886 snd_device);
887 enable_snd_device(adev, d_device);
888 /* Update the out_snd_device before enabling the audio route */
889 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 }
891 }
892
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 /* Re-route all the usecases on the shared backend other than the
894 specified usecase to new snd devices */
895 list_for_each(node, &adev->usecase_list) {
896 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700898 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 }
900 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 }
902}
903
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700904static void check_and_route_capture_usecases(struct audio_device *adev,
905 struct audio_usecase *uc_info,
906 snd_device_t snd_device)
907{
908 struct listnode *node;
909 struct audio_usecase *usecase;
910 bool switch_device[AUDIO_USECASE_MAX];
911 int i, num_uc_to_switch = 0;
912
vivek mehta4ed66e62016-04-15 23:33:34 -0700913 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
914
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700915 /*
916 * This function is to make sure that all the active capture usecases
917 * are always routed to the same input sound device.
918 * For example, if audio-record and voice-call usecases are currently
919 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
920 * is received for voice call then we have to make sure that audio-record
921 * usecase is also switched to earpiece i.e. voice-dmic-ef,
922 * because of the limitation that two devices cannot be enabled
923 * at the same time if they share the same backend.
924 */
925 for (i = 0; i < AUDIO_USECASE_MAX; i++)
926 switch_device[i] = false;
927
928 list_for_each(node, &adev->usecase_list) {
929 usecase = node_to_item(node, struct audio_usecase, list);
930 if (usecase->type != PCM_PLAYBACK &&
931 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700932 usecase->in_snd_device != snd_device &&
933 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700934 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
935 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700936 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700937 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 switch_device[usecase->id] = true;
939 num_uc_to_switch++;
940 }
941 }
942
943 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700944 list_for_each(node, &adev->usecase_list) {
945 usecase = node_to_item(node, struct audio_usecase, list);
946 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700947 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700948 }
949 }
950
951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
953 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700954 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700955 }
956 }
957
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700958 /* Re-route all the usecases on the shared backend other than the
959 specified usecase to new snd devices */
960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 /* Update the in_snd_device only before enabling the audio route */
963 if (switch_device[usecase->id] ) {
964 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700965 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700966 }
967 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700968 }
969}
970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700972static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700974 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700975 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976
977 switch (channels) {
978 /*
979 * Do not handle stereo output in Multi-channel cases
980 * Stereo case is handled in normal playback path
981 */
982 case 6:
983 ALOGV("%s: HDMI supports 5.1", __func__);
984 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
985 break;
986 case 8:
987 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
988 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
989 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
990 break;
991 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700992 ALOGE("HDMI does not support multi channel playback");
993 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994 break;
995 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700996 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997}
998
Andy Hung18859412017-08-09 11:47:21 -0700999static ssize_t read_usb_sup_sample_rates(bool is_playback,
1000 uint32_t *supported_sample_rates,
1001 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001002{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001003 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1004 supported_sample_rates,
1005 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001006#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001007 for (ssize_t i=0; i<count; i++) {
1008 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1009 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010 }
1011#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001012 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001013}
1014
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015static int read_usb_sup_channel_masks(bool is_playback,
1016 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001017 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001018{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001019 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001020 int channel_count;
1021 uint32_t num_masks = 0;
1022 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1023 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001024 }
Eric Laurent74b55762017-07-09 17:04:53 -07001025 if (is_playback) {
1026 // For playback we never report mono because the framework always outputs stereo
1027 channel_count = DEFAULT_CHANNEL_COUNT;
1028 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1029 // above 2 but we want indexed masks here. So we
1030 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1031 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1032 }
1033 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1034 supported_channel_masks[num_masks++] =
1035 audio_channel_mask_for_index_assignment_from_count(channel_count);
1036 }
1037 } else {
1038 // For capture we report all supported channel masks from 1 channel up.
1039 channel_count = MIN_CHANNEL_COUNT;
1040 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1041 // indexed mask
1042 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1043 supported_channel_masks[num_masks++] =
1044 audio_channel_in_mask_from_count(channel_count);
1045 }
1046 }
1047 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1048 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1049 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001050}
1051
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001052static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001053 audio_format_t *supported_formats,
1054 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001055{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001056 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001057 switch (bitwidth) {
1058 case 24:
1059 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001060 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001061 break;
1062 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001063 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001064 break;
1065 case 16:
1066 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001067 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001068 break;
1069 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 ALOGV("%s: %s supported format %d", __func__,
1071 is_playback ? "P" : "C", bitwidth);
1072 return 1;
1073}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001074
Haynes Mathew George569b7482017-05-08 14:44:27 -07001075static int read_usb_sup_params_and_compare(bool is_playback,
1076 audio_format_t *format,
1077 audio_format_t *supported_formats,
1078 uint32_t max_formats,
1079 audio_channel_mask_t *mask,
1080 audio_channel_mask_t *supported_channel_masks,
1081 uint32_t max_masks,
1082 uint32_t *rate,
1083 uint32_t *supported_sample_rates,
1084 uint32_t max_rates) {
1085 int ret = 0;
1086 int num_formats;
1087 int num_masks;
1088 int num_rates;
1089 int i;
1090
1091 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1092 max_formats);
1093 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1094 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001095
Haynes Mathew George569b7482017-05-08 14:44:27 -07001096 num_rates = read_usb_sup_sample_rates(is_playback,
1097 supported_sample_rates, max_rates);
1098
1099#define LUT(table, len, what, dflt) \
1100 for (i=0; i<len && (table[i] != what); i++); \
1101 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1102
1103 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1104 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1105 LUT(supported_sample_rates, num_rates, *rate, 0);
1106
1107#undef LUT
1108 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001109}
1110
Andy Hungd9653bd2017-08-01 19:31:39 -07001111static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1112{
1113 // Check if usb is ready.
1114 // The usb device may have been removed quickly after insertion and hence
1115 // no longer available. This will show up as empty channel masks, or rates.
1116
1117 pthread_mutex_lock(&adev->lock);
1118 uint32_t supported_sample_rate;
1119
1120 // we consider usb ready if we can fetch at least one sample rate.
1121 const bool ready = read_usb_sup_sample_rates(
1122 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1123 pthread_mutex_unlock(&adev->lock);
1124 return ready;
1125}
1126
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001127static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1128{
1129 struct audio_usecase *usecase;
1130 struct listnode *node;
1131
1132 list_for_each(node, &adev->usecase_list) {
1133 usecase = node_to_item(node, struct audio_usecase, list);
1134 if (usecase->type == VOICE_CALL) {
1135 ALOGV("%s: usecase id %d", __func__, usecase->id);
1136 return usecase->id;
1137 }
1138 }
1139 return USECASE_INVALID;
1140}
1141
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001142struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1143 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144{
1145 struct audio_usecase *usecase;
1146 struct listnode *node;
1147
1148 list_for_each(node, &adev->usecase_list) {
1149 usecase = node_to_item(node, struct audio_usecase, list);
1150 if (usecase->id == uc_id)
1151 return usecase;
1152 }
1153 return NULL;
1154}
1155
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001156int select_devices(struct audio_device *adev,
1157 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001159 snd_device_t out_snd_device = SND_DEVICE_NONE;
1160 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001161 struct audio_usecase *usecase = NULL;
1162 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001163 struct audio_usecase *hfp_usecase = NULL;
1164 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001165 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001168 usecase = get_usecase_from_list(adev, uc_id);
1169 if (usecase == NULL) {
1170 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1171 return -EINVAL;
1172 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001174 if ((usecase->type == VOICE_CALL) ||
1175 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001176 out_snd_device = platform_get_output_snd_device(adev->platform,
1177 usecase->stream.out->devices);
1178 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 usecase->devices = usecase->stream.out->devices;
1180 } else {
1181 /*
1182 * If the voice call is active, use the sound devices of voice call usecase
1183 * so that it would not result any device switch. All the usecases will
1184 * be switched to new device when select_devices() is called for voice call
1185 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001186 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001188 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001189 vc_usecase = get_usecase_from_list(adev,
1190 get_voice_usecase_id_from_list(adev));
1191 if ((vc_usecase != NULL) &&
1192 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1193 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 in_snd_device = vc_usecase->in_snd_device;
1195 out_snd_device = vc_usecase->out_snd_device;
1196 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001197 } else if (audio_extn_hfp_is_active(adev)) {
1198 hfp_ucid = audio_extn_hfp_get_usecase();
1199 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1200 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1201 in_snd_device = hfp_usecase->in_snd_device;
1202 out_snd_device = hfp_usecase->out_snd_device;
1203 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001204 }
1205 if (usecase->type == PCM_PLAYBACK) {
1206 usecase->devices = usecase->stream.out->devices;
1207 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001208 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001209 struct stream_out *voip_out = adev->primary_output;
1210 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1211 USECASE_AUDIO_PLAYBACK_VOIP);
1212
Eric Laurentb23d5282013-05-14 15:27:20 -07001213 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001214 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001215
1216 if (voip_usecase)
1217 voip_out = voip_usecase->stream.out;
1218
1219 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001220 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001221 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001222 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001223 select_devices(adev, adev->active_input->usecase);
1224 }
1225 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 } else if (usecase->type == PCM_CAPTURE) {
1227 usecase->devices = usecase->stream.in->device;
1228 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001229 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001230 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001231 if (adev->active_input &&
1232 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1233 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001234
1235 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1236 USECASE_AUDIO_PLAYBACK_VOIP);
1237
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001238 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001239 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1240 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001241 } else if (voip_usecase) {
1242 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001243 } else if (adev->primary_output) {
1244 out_device = adev->primary_output->devices;
1245 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001246 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001247 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001248 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001249 }
1250 }
1251
1252 if (out_snd_device == usecase->out_snd_device &&
1253 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001254 return 0;
1255 }
1256
Eric Laurent2bafff12016-03-17 12:17:23 -07001257 if (out_snd_device != SND_DEVICE_NONE &&
1258 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1259 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1260 __func__,
1261 use_case_table[uc_id],
1262 adev->last_logged_snd_device[uc_id][0],
1263 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1264 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1265 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1266 -1,
1267 out_snd_device,
1268 platform_get_snd_device_name(out_snd_device),
1269 platform_get_snd_device_acdb_id(out_snd_device));
1270 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1271 }
1272 if (in_snd_device != SND_DEVICE_NONE &&
1273 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1274 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1275 __func__,
1276 use_case_table[uc_id],
1277 adev->last_logged_snd_device[uc_id][1],
1278 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1279 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1280 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1281 -1,
1282 in_snd_device,
1283 platform_get_snd_device_name(in_snd_device),
1284 platform_get_snd_device_acdb_id(in_snd_device));
1285 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1286 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001287
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001288 /*
1289 * Limitation: While in call, to do a device switch we need to disable
1290 * and enable both RX and TX devices though one of them is same as current
1291 * device.
1292 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001293 if ((usecase->type == VOICE_CALL) &&
1294 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1295 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001296 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001297 /* Disable sidetone only if voice call already exists */
1298 if (voice_is_call_state_active(adev))
1299 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001300 }
1301
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001302 /* Disable current sound devices */
1303 if (usecase->out_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->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001306 }
1307
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001309 disable_audio_route(adev, usecase);
1310 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001311 }
1312
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001313 /* Applicable only on the targets that has external modem.
1314 * New device information should be sent to modem before enabling
1315 * the devices to reduce in-call device switch time.
1316 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001317 if ((usecase->type == VOICE_CALL) &&
1318 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1319 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001320 status = platform_switch_voice_call_enable_device_config(adev->platform,
1321 out_snd_device,
1322 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001323 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001324
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001325 /* Enable new sound devices */
1326 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001327 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001328 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001329 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001330 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001331 }
1332
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001333 if (in_snd_device != SND_DEVICE_NONE) {
1334 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001335 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001336 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001337
Eric Laurentb23d5282013-05-14 15:27:20 -07001338 if (usecase->type == VOICE_CALL)
1339 status = platform_switch_voice_call_device_post(adev->platform,
1340 out_snd_device,
1341 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001342
sangwoo170731f2013-06-08 15:36:36 +09001343 usecase->in_snd_device = in_snd_device;
1344 usecase->out_snd_device = out_snd_device;
1345
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001346 audio_extn_tfa_98xx_set_mode();
1347
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001348 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001349
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001350 /* Applicable only on the targets that has external modem.
1351 * Enable device command should be sent to modem only after
1352 * enabling voice call mixer controls
1353 */
vivek mehta765eb642015-08-07 19:46:06 -07001354 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001355 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1356 out_snd_device,
1357 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001358 /* Enable sidetone only if voice call already exists */
1359 if (voice_is_call_state_active(adev))
1360 voice_set_sidetone(adev, out_snd_device, true);
1361 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001363 return status;
1364}
1365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001366static int stop_input_stream(struct stream_in *in)
1367{
1368 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001369 struct audio_usecase *uc_info;
1370 struct audio_device *adev = in->dev;
1371
Eric Laurent994a6932013-07-17 11:51:42 -07001372 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001373 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001374
1375 if (adev->active_input) {
1376 if (adev->active_input->usecase == in->usecase) {
1377 adev->active_input = NULL;
1378 } else {
1379 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1380 __func__,
1381 use_case_table[adev->active_input->usecase],
1382 use_case_table[in->usecase]);
1383 }
1384 }
1385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001386 uc_info = get_usecase_from_list(adev, in->usecase);
1387 if (uc_info == NULL) {
1388 ALOGE("%s: Could not find the usecase (%d) in the list",
1389 __func__, in->usecase);
1390 return -EINVAL;
1391 }
1392
vivek mehta781065c2017-04-04 12:55:01 -07001393 /* Close in-call recording streams */
1394 voice_check_and_stop_incall_rec_usecase(adev, in);
1395
Eric Laurent150dbfe2013-02-27 14:31:02 -08001396 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001397 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001398
1399 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001400 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001401
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001402 list_remove(&uc_info->list);
1403 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404
Eric Laurent994a6932013-07-17 11:51:42 -07001405 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001406 return ret;
1407}
1408
1409int start_input_stream(struct stream_in *in)
1410{
1411 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001412 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001413 struct audio_usecase *uc_info;
1414 struct audio_device *adev = in->dev;
1415
Eric Laurent994a6932013-07-17 11:51:42 -07001416 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001417
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001418 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1419 return -EIO;
1420
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001421 if (in->card_status == CARD_STATUS_OFFLINE ||
1422 adev->card_status == CARD_STATUS_OFFLINE) {
1423 ALOGW("in->card_status or adev->card_status offline, try again");
1424 ret = -EAGAIN;
1425 goto error_config;
1426 }
1427
vivek mehta781065c2017-04-04 12:55:01 -07001428 /* Check if source matches incall recording usecase criteria */
1429 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1430 if (ret)
1431 goto error_config;
1432 else
1433 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1434
Eric Laurentb23d5282013-05-14 15:27:20 -07001435 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436 if (in->pcm_device_id < 0) {
1437 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1438 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001439 ret = -EINVAL;
1440 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001442
1443 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1445 uc_info->id = in->usecase;
1446 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001447 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448 uc_info->devices = in->device;
1449 uc_info->in_snd_device = SND_DEVICE_NONE;
1450 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001452 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001453
1454 audio_extn_perf_lock_acquire();
1455
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001456 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457
Eric Laurent0e46adf2016-12-16 12:49:24 -08001458 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001459 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001460 ALOGE("%s: pcm stream not ready", __func__);
1461 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001462 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001463 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001464 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001465 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1466 goto error_open;
1467 }
1468 } else {
1469 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1470 unsigned int pcm_open_retry_count = 0;
1471
1472 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1473 flags |= PCM_MMAP | PCM_NOIRQ;
1474 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1475 } else if (in->realtime) {
1476 flags |= PCM_MMAP | PCM_NOIRQ;
1477 }
1478
1479 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1480 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1481
1482 while (1) {
1483 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1484 flags, &in->config);
1485 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1486 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1487 if (in->pcm != NULL) {
1488 pcm_close(in->pcm);
1489 in->pcm = NULL;
1490 }
1491 if (pcm_open_retry_count-- == 0) {
1492 ret = -EIO;
1493 goto error_open;
1494 }
1495 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1496 continue;
1497 }
1498 break;
1499 }
1500
1501 ALOGV("%s: pcm_prepare", __func__);
1502 ret = pcm_prepare(in->pcm);
1503 if (ret < 0) {
1504 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001505 pcm_close(in->pcm);
1506 in->pcm = NULL;
1507 goto error_open;
1508 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001509 if (in->realtime) {
1510 ret = pcm_start(in->pcm);
1511 if (ret < 0) {
1512 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1513 pcm_close(in->pcm);
1514 in->pcm = NULL;
1515 goto error_open;
1516 }
1517 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001518 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001519 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001520 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001521 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001522
Eric Laurent0e46adf2016-12-16 12:49:24 -08001523 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001524
1525error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001527 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001528
1529error_config:
1530 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001531 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001532 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533}
1534
Eric Laurenta1478072015-09-21 17:21:52 -07001535void lock_input_stream(struct stream_in *in)
1536{
1537 pthread_mutex_lock(&in->pre_lock);
1538 pthread_mutex_lock(&in->lock);
1539 pthread_mutex_unlock(&in->pre_lock);
1540}
1541
1542void lock_output_stream(struct stream_out *out)
1543{
1544 pthread_mutex_lock(&out->pre_lock);
1545 pthread_mutex_lock(&out->lock);
1546 pthread_mutex_unlock(&out->pre_lock);
1547}
1548
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001549/* must be called with out->lock locked */
1550static int send_offload_cmd_l(struct stream_out* out, int command)
1551{
1552 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1553
1554 ALOGVV("%s %d", __func__, command);
1555
1556 cmd->cmd = command;
1557 list_add_tail(&out->offload_cmd_list, &cmd->node);
1558 pthread_cond_signal(&out->offload_cond);
1559 return 0;
1560}
1561
1562/* must be called iwth out->lock locked */
1563static void stop_compressed_output_l(struct stream_out *out)
1564{
1565 out->offload_state = OFFLOAD_STATE_IDLE;
1566 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001567 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001568 if (out->compr != NULL) {
1569 compress_stop(out->compr);
1570 while (out->offload_thread_blocked) {
1571 pthread_cond_wait(&out->cond, &out->lock);
1572 }
1573 }
1574}
1575
1576static void *offload_thread_loop(void *context)
1577{
1578 struct stream_out *out = (struct stream_out *) context;
1579 struct listnode *item;
1580
1581 out->offload_state = OFFLOAD_STATE_IDLE;
1582 out->playback_started = 0;
1583
1584 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1585 set_sched_policy(0, SP_FOREGROUND);
1586 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1587
1588 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001589 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001590 for (;;) {
1591 struct offload_cmd *cmd = NULL;
1592 stream_callback_event_t event;
1593 bool send_callback = false;
1594
1595 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1596 __func__, list_empty(&out->offload_cmd_list),
1597 out->offload_state);
1598 if (list_empty(&out->offload_cmd_list)) {
1599 ALOGV("%s SLEEPING", __func__);
1600 pthread_cond_wait(&out->offload_cond, &out->lock);
1601 ALOGV("%s RUNNING", __func__);
1602 continue;
1603 }
1604
1605 item = list_head(&out->offload_cmd_list);
1606 cmd = node_to_item(item, struct offload_cmd, node);
1607 list_remove(item);
1608
1609 ALOGVV("%s STATE %d CMD %d out->compr %p",
1610 __func__, out->offload_state, cmd->cmd, out->compr);
1611
1612 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1613 free(cmd);
1614 break;
1615 }
1616
1617 if (out->compr == NULL) {
1618 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001619 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001620 pthread_cond_signal(&out->cond);
1621 continue;
1622 }
1623 out->offload_thread_blocked = true;
1624 pthread_mutex_unlock(&out->lock);
1625 send_callback = false;
1626 switch(cmd->cmd) {
1627 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1628 compress_wait(out->compr, -1);
1629 send_callback = true;
1630 event = STREAM_CBK_EVENT_WRITE_READY;
1631 break;
1632 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001633 compress_next_track(out->compr);
1634 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001635 send_callback = true;
1636 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001637 /* Resend the metadata for next iteration */
1638 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001639 break;
1640 case OFFLOAD_CMD_DRAIN:
1641 compress_drain(out->compr);
1642 send_callback = true;
1643 event = STREAM_CBK_EVENT_DRAIN_READY;
1644 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001645 case OFFLOAD_CMD_ERROR:
1646 send_callback = true;
1647 event = STREAM_CBK_EVENT_ERROR;
1648 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001649 default:
1650 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1651 break;
1652 }
Eric Laurenta1478072015-09-21 17:21:52 -07001653 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001654 out->offload_thread_blocked = false;
1655 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001656 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001657 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001658 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001659 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001660 free(cmd);
1661 }
1662
1663 pthread_cond_signal(&out->cond);
1664 while (!list_empty(&out->offload_cmd_list)) {
1665 item = list_head(&out->offload_cmd_list);
1666 list_remove(item);
1667 free(node_to_item(item, struct offload_cmd, node));
1668 }
1669 pthread_mutex_unlock(&out->lock);
1670
1671 return NULL;
1672}
1673
1674static int create_offload_callback_thread(struct stream_out *out)
1675{
1676 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1677 list_init(&out->offload_cmd_list);
1678 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1679 offload_thread_loop, out);
1680 return 0;
1681}
1682
1683static int destroy_offload_callback_thread(struct stream_out *out)
1684{
Eric Laurenta1478072015-09-21 17:21:52 -07001685 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001686 stop_compressed_output_l(out);
1687 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1688
1689 pthread_mutex_unlock(&out->lock);
1690 pthread_join(out->offload_thread, (void **) NULL);
1691 pthread_cond_destroy(&out->offload_cond);
1692
1693 return 0;
1694}
1695
Eric Laurent07eeafd2013-10-06 12:52:49 -07001696static bool allow_hdmi_channel_config(struct audio_device *adev)
1697{
1698 struct listnode *node;
1699 struct audio_usecase *usecase;
1700 bool ret = true;
1701
1702 list_for_each(node, &adev->usecase_list) {
1703 usecase = node_to_item(node, struct audio_usecase, list);
1704 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1705 /*
1706 * If voice call is already existing, do not proceed further to avoid
1707 * disabling/enabling both RX and TX devices, CSD calls, etc.
1708 * Once the voice call done, the HDMI channels can be configured to
1709 * max channels of remaining use cases.
1710 */
1711 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001712 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001713 __func__);
1714 ret = false;
1715 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001716 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1717 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001718 "no change in HDMI channels", __func__);
1719 ret = false;
1720 break;
1721 }
1722 }
1723 }
1724 return ret;
1725}
1726
1727static int check_and_set_hdmi_channels(struct audio_device *adev,
1728 unsigned int channels)
1729{
1730 struct listnode *node;
1731 struct audio_usecase *usecase;
1732
1733 /* Check if change in HDMI channel config is allowed */
1734 if (!allow_hdmi_channel_config(adev))
1735 return 0;
1736
1737 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001738 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001739 return 0;
1740 }
1741
1742 platform_set_hdmi_channels(adev->platform, channels);
1743 adev->cur_hdmi_channels = channels;
1744
1745 /*
1746 * Deroute all the playback streams routed to HDMI so that
1747 * the back end is deactivated. Note that backend will not
1748 * be deactivated if any one stream is connected to it.
1749 */
1750 list_for_each(node, &adev->usecase_list) {
1751 usecase = node_to_item(node, struct audio_usecase, list);
1752 if (usecase->type == PCM_PLAYBACK &&
1753 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001754 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001755 }
1756 }
1757
1758 /*
1759 * Enable all the streams disabled above. Now the HDMI backend
1760 * will be activated with new channel configuration
1761 */
1762 list_for_each(node, &adev->usecase_list) {
1763 usecase = node_to_item(node, struct audio_usecase, list);
1764 if (usecase->type == PCM_PLAYBACK &&
1765 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001766 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001767 }
1768 }
1769
1770 return 0;
1771}
1772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773static int stop_output_stream(struct stream_out *out)
1774{
1775 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776 struct audio_usecase *uc_info;
1777 struct audio_device *adev = out->dev;
1778
Eric Laurent994a6932013-07-17 11:51:42 -07001779 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001780 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781 uc_info = get_usecase_from_list(adev, out->usecase);
1782 if (uc_info == NULL) {
1783 ALOGE("%s: Could not find the usecase (%d) in the list",
1784 __func__, out->usecase);
1785 return -EINVAL;
1786 }
1787
Haynes Mathew George41f86652014-06-17 14:22:15 -07001788 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1789 if (adev->visualizer_stop_output != NULL)
1790 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1791 if (adev->offload_effects_stop_output != NULL)
1792 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1793 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001794
Eric Laurent150dbfe2013-02-27 14:31:02 -08001795 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001796 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001797
1798 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001799 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001801 list_remove(&uc_info->list);
1802 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803
Eric Laurent0499d4f2014-08-25 22:39:29 -05001804 audio_extn_extspk_update(adev->extspk);
1805
Eric Laurent07eeafd2013-10-06 12:52:49 -07001806 /* Must be called after removing the usecase from list */
1807 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1808 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001809 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1810 struct listnode *node;
1811 struct audio_usecase *usecase;
1812 list_for_each(node, &adev->usecase_list) {
1813 usecase = node_to_item(node, struct audio_usecase, list);
1814 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1815 select_devices(adev, usecase->id);
1816 }
1817 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001818
Eric Laurent994a6932013-07-17 11:51:42 -07001819 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820 return ret;
1821}
1822
1823int start_output_stream(struct stream_out *out)
1824{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826 struct audio_usecase *uc_info;
1827 struct audio_device *adev = out->dev;
1828
Eric Laurent994a6932013-07-17 11:51:42 -07001829 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001830 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001831
1832 if (out->card_status == CARD_STATUS_OFFLINE ||
1833 adev->card_status == CARD_STATUS_OFFLINE) {
1834 ALOGW("out->card_status or adev->card_status offline, try again");
1835 ret = -EAGAIN;
1836 goto error_config;
1837 }
1838
Eric Laurentb23d5282013-05-14 15:27:20 -07001839 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001840 if (out->pcm_device_id < 0) {
1841 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1842 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001843 ret = -EINVAL;
1844 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 }
1846
1847 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1848 uc_info->id = out->usecase;
1849 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001850 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001851 uc_info->devices = out->devices;
1852 uc_info->in_snd_device = SND_DEVICE_NONE;
1853 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854
Eric Laurent07eeafd2013-10-06 12:52:49 -07001855 /* This must be called before adding this usecase to the list */
1856 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1857 check_and_set_hdmi_channels(adev, out->config.channels);
1858
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001859 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001861 audio_extn_perf_lock_acquire();
1862
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001863 select_devices(adev, out->usecase);
1864
Eric Laurent0499d4f2014-08-25 22:39:29 -05001865 audio_extn_extspk_update(adev->extspk);
1866
Andy Hung31aca912014-03-20 17:14:59 -07001867 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001868 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001869 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1870 out->pcm = NULL;
1871 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1872 COMPRESS_IN, &out->compr_config);
1873 if (out->compr && !is_compress_ready(out->compr)) {
1874 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1875 compress_close(out->compr);
1876 out->compr = NULL;
1877 ret = -EIO;
1878 goto error_open;
1879 }
1880 if (out->offload_callback)
1881 compress_nonblock(out->compr, out->non_blocking);
1882
1883 if (adev->visualizer_start_output != NULL)
1884 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1885 if (adev->offload_effects_start_output != NULL)
1886 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1887 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001888 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001889 ALOGE("%s: pcm stream not ready", __func__);
1890 goto error_open;
1891 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001892 ret = pcm_start(out->pcm);
1893 if (ret < 0) {
1894 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1895 goto error_open;
1896 }
1897 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001898 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001899 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001900
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001901 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1902 flags |= PCM_MMAP | PCM_NOIRQ;
1903 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001904 } else if (out->realtime) {
1905 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001906 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001907
1908 while (1) {
1909 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1910 flags, &out->config);
1911 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1912 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1913 if (out->pcm != NULL) {
1914 pcm_close(out->pcm);
1915 out->pcm = NULL;
1916 }
1917 if (pcm_open_retry_count-- == 0) {
1918 ret = -EIO;
1919 goto error_open;
1920 }
1921 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1922 continue;
1923 }
1924 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001925 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001926 ALOGV("%s: pcm_prepare", __func__);
1927 if (pcm_is_ready(out->pcm)) {
1928 ret = pcm_prepare(out->pcm);
1929 if (ret < 0) {
1930 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1931 pcm_close(out->pcm);
1932 out->pcm = NULL;
1933 goto error_open;
1934 }
1935 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001936 if (out->realtime) {
1937 ret = pcm_start(out->pcm);
1938 if (ret < 0) {
1939 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1940 pcm_close(out->pcm);
1941 out->pcm = NULL;
1942 goto error_open;
1943 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001944 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001945 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001946 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001947 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001948 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001949 audio_extn_utils_send_app_type_gain(out->dev,
1950 out->app_type_cfg.app_type,
1951 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001952
1953 // consider a scenario where on pause lower layers are tear down.
1954 // so on resume, swap mixer control need to be sent only when
1955 // backend is active, hence rather than sending from enable device
1956 // sending it from start of streamtream
1957
1958 platform_set_swap_channels(adev, true);
1959
Eric Laurent994a6932013-07-17 11:51:42 -07001960 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001961 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001962error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001963 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001965error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001966 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967}
1968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969static int check_input_parameters(uint32_t sample_rate,
1970 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001971 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001973 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1974 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001975 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1976 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001977 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1978 return -EINVAL;
1979 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980
Eric Laurent74b55762017-07-09 17:04:53 -07001981 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1982 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001983 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001984 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001985 return -EINVAL;
1986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987
1988 switch (sample_rate) {
1989 case 8000:
1990 case 11025:
1991 case 12000:
1992 case 16000:
1993 case 22050:
1994 case 24000:
1995 case 32000:
1996 case 44100:
1997 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001998 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 break;
2000 default:
vivek mehtadae44712015-07-27 14:13:18 -07002001 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 return -EINVAL;
2003 }
2004
2005 return 0;
2006}
2007
vivek mehtaa68fea62017-06-08 19:04:02 -07002008static size_t get_stream_buffer_size(size_t duration_ms,
2009 uint32_t sample_rate,
2010 audio_format_t format,
2011 int channel_count,
2012 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013{
2014 size_t size = 0;
2015
vivek mehtaa68fea62017-06-08 19:04:02 -07002016 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002017 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002018 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002019
2020 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021
Glenn Kasten4f993392014-05-14 07:30:48 -07002022 /* make sure the size is multiple of 32 bytes
2023 * At 48 kHz mono 16-bit PCM:
2024 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2025 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2026 */
2027 size += 0x1f;
2028 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002029
2030 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031}
2032
2033static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2034{
2035 struct stream_out *out = (struct stream_out *)stream;
2036
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038}
2039
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002040static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041{
2042 return -ENOSYS;
2043}
2044
2045static size_t out_get_buffer_size(const struct audio_stream *stream)
2046{
2047 struct stream_out *out = (struct stream_out *)stream;
2048
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002049 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2050 return out->compr_config.fragment_size;
2051 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002052 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002053 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002054}
2055
2056static uint32_t out_get_channels(const struct audio_stream *stream)
2057{
2058 struct stream_out *out = (struct stream_out *)stream;
2059
2060 return out->channel_mask;
2061}
2062
2063static audio_format_t out_get_format(const struct audio_stream *stream)
2064{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002065 struct stream_out *out = (struct stream_out *)stream;
2066
2067 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068}
2069
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002070static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071{
2072 return -ENOSYS;
2073}
2074
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002075/* must be called with out->lock locked */
2076static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077{
2078 struct stream_out *out = (struct stream_out *)stream;
2079 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002080 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002083 if (adev->adm_deregister_stream)
2084 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002085 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002087 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2088 if (out->pcm) {
2089 pcm_close(out->pcm);
2090 out->pcm = NULL;
2091 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002092 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002093 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002094 out->playback_started = false;
2095 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002096 } else {
2097 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002098 out->gapless_mdata.encoder_delay = 0;
2099 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002100 if (out->compr != NULL) {
2101 compress_close(out->compr);
2102 out->compr = NULL;
2103 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002104 }
Phil Burkbc991042017-02-24 08:06:44 -08002105 if (do_stop) {
2106 stop_output_stream(out);
2107 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002108 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002110 return 0;
2111}
2112
2113static int out_standby(struct audio_stream *stream)
2114{
2115 struct stream_out *out = (struct stream_out *)stream;
2116
2117 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2118 out->usecase, use_case_table[out->usecase]);
2119
2120 lock_output_stream(out);
2121 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002123 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124 return 0;
2125}
2126
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002127static int out_on_error(struct audio_stream *stream)
2128{
2129 struct stream_out *out = (struct stream_out *)stream;
2130 struct audio_device *adev = out->dev;
2131 bool do_standby = false;
2132
2133 lock_output_stream(out);
2134 if (!out->standby) {
2135 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2136 stop_compressed_output_l(out);
2137 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2138 } else
2139 do_standby = true;
2140 }
2141 pthread_mutex_unlock(&out->lock);
2142
2143 if (do_standby)
2144 return out_standby(&out->stream.common);
2145
2146 return 0;
2147}
2148
Andy Hung7401c7c2016-09-21 12:41:21 -07002149static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150{
Andy Hung7401c7c2016-09-21 12:41:21 -07002151 struct stream_out *out = (struct stream_out *)stream;
2152
2153 // We try to get the lock for consistency,
2154 // but it isn't necessary for these variables.
2155 // If we're not in standby, we may be blocked on a write.
2156 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2157 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2158 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2159
2160 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002161 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002162 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002163
2164 // dump error info
2165 (void)error_log_dump(
2166 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 return 0;
2169}
2170
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002171static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2172{
2173 int ret = 0;
2174 char value[32];
2175 struct compr_gapless_mdata tmp_mdata;
2176
2177 if (!out || !parms) {
2178 return -EINVAL;
2179 }
2180
2181 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2182 if (ret >= 0) {
2183 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2184 } else {
2185 return -EINVAL;
2186 }
2187
2188 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2189 if (ret >= 0) {
2190 tmp_mdata.encoder_padding = atoi(value);
2191 } else {
2192 return -EINVAL;
2193 }
2194
2195 out->gapless_mdata = tmp_mdata;
2196 out->send_new_metadata = 1;
2197 ALOGV("%s new encoder delay %u and padding %u", __func__,
2198 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2199
2200 return 0;
2201}
2202
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002203static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2204{
2205 return out == adev->primary_output || out == adev->voice_tx_output;
2206}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002207
Kevin Rocard1e02c882017-08-09 15:26:07 -07002208static int get_alive_usb_card(struct str_parms* parms) {
2209 int card;
2210 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2211 !audio_extn_usb_alive(card)) {
2212 return card;
2213 }
2214 return -ENODEV;
2215}
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2218{
2219 struct stream_out *out = (struct stream_out *)stream;
2220 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002221 struct audio_usecase *usecase;
2222 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 struct str_parms *parms;
2224 char value[32];
2225 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002226 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002227 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002228
Eric Laurent2e140aa2016-06-30 17:14:46 -07002229 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002230 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 parms = str_parms_create_str(kvpairs);
2232 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2233 if (ret >= 0) {
2234 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002235
Eric Laurenta1478072015-09-21 17:21:52 -07002236 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002237
2238 // The usb driver needs to be closed after usb device disconnection
2239 // otherwise audio is no longer played on the new usb devices.
2240 // By forcing the stream in standby, the usb stack refcount drops to 0
2241 // and the driver is closed.
2242 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2243 audio_is_usb_out_device(out->devices)) {
2244 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2245 out_standby_l(&out->stream.common);
2246 }
2247
Eric Laurent150dbfe2013-02-27 14:31:02 -08002248 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002250 /*
2251 * When HDMI cable is unplugged the music playback is paused and
2252 * the policy manager sends routing=0. But the audioflinger
2253 * continues to write data until standby time (3sec).
2254 * As the HDMI core is turned off, the write gets blocked.
2255 * Avoid this by routing audio to speaker until standby.
2256 */
2257 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2258 val == AUDIO_DEVICE_NONE) {
2259 val = AUDIO_DEVICE_OUT_SPEAKER;
2260 }
2261
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002262 audio_devices_t new_dev = val;
2263
2264 // Workaround: If routing to an non existing usb device, fail gracefully
2265 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002266 int card;
2267 if (audio_is_usb_out_device(new_dev) &&
2268 (card = get_alive_usb_card(parms)) >= 0) {
2269
2270 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002271 pthread_mutex_unlock(&adev->lock);
2272 pthread_mutex_unlock(&out->lock);
2273 status = -ENOSYS;
2274 goto routing_fail;
2275 }
2276
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002277 /*
2278 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002279 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002280 * the select_devices(). But how do we undo this?
2281 *
2282 * For example, music playback is active on headset (deep-buffer usecase)
2283 * and if we go to ringtones and select a ringtone, low-latency usecase
2284 * will be started on headset+speaker. As we can't enable headset+speaker
2285 * and headset devices at the same time, select_devices() switches the music
2286 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2287 * So when the ringtone playback is completed, how do we undo the same?
2288 *
2289 * We are relying on the out_set_parameters() call on deep-buffer output,
2290 * once the ringtone playback is ended.
2291 * NOTE: We should not check if the current devices are same as new devices.
2292 * Because select_devices() must be called to switch back the music
2293 * playback to headset.
2294 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002295 if (new_dev != AUDIO_DEVICE_NONE) {
2296 bool same_dev = out->devices == new_dev;
2297 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002298
Eric Laurenta7657192014-10-09 21:09:33 -07002299 if (output_drives_call(adev, out)) {
2300 if (!voice_is_in_call(adev)) {
2301 if (adev->mode == AUDIO_MODE_IN_CALL) {
2302 adev->current_call_output = out;
2303 ret = voice_start_call(adev);
2304 }
2305 } else {
2306 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002307 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002308 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002309 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002310
2311 if (!out->standby) {
2312 if (!same_dev) {
2313 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002314 // inform adm before actual routing to prevent glitches.
2315 if (adev->adm_on_routing_change) {
2316 adev->adm_on_routing_change(adev->adm_data,
2317 out->handle);
2318 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002319 }
2320 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002321 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002322
2323 // on device switch force swap, lower functions will make sure
2324 // to check if swap is allowed or not.
2325
2326 if (!same_dev)
2327 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002328 }
2329
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002330 }
2331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002333 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002334
2335 /*handles device and call state changes*/
2336 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002337 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002338 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002339
2340 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2341 parse_compress_metadata(out, parms);
2342 }
2343
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002344 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002345 ALOGV("%s: exit: code(%d)", __func__, status);
2346 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347}
2348
Haynes Mathew George569b7482017-05-08 14:44:27 -07002349static bool stream_get_parameter_channels(struct str_parms *query,
2350 struct str_parms *reply,
2351 audio_channel_mask_t *supported_channel_masks) {
2352 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002353 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002355 size_t i, j;
2356
2357 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2358 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002359 value[0] = '\0';
2360 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002361 while (supported_channel_masks[i] != 0) {
2362 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2363 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002364 if (!first) {
2365 strcat(value, "|");
2366 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002367 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368 first = false;
2369 break;
2370 }
2371 }
2372 i++;
2373 }
2374 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002375 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002376 return ret >= 0;
2377}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002378
Haynes Mathew George569b7482017-05-08 14:44:27 -07002379static bool stream_get_parameter_formats(struct str_parms *query,
2380 struct str_parms *reply,
2381 audio_format_t *supported_formats) {
2382 int ret = -1;
2383 char value[256];
2384 int i;
2385
2386 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2387 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002388 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002389 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002390 case AUDIO_FORMAT_PCM_16_BIT:
2391 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2392 break;
2393 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2394 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2395 break;
2396 case AUDIO_FORMAT_PCM_32_BIT:
2397 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2398 break;
2399 default:
2400 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002401 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002402 break;
2403 }
2404 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002405 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002406 return ret >= 0;
2407}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002408
Haynes Mathew George569b7482017-05-08 14:44:27 -07002409static bool stream_get_parameter_rates(struct str_parms *query,
2410 struct str_parms *reply,
2411 uint32_t *supported_sample_rates) {
2412
2413 int i;
2414 char value[256];
2415 int ret = -1;
2416 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2417 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002418 value[0] = '\0';
2419 i=0;
2420 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002421 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002422 int avail = sizeof(value) - cursor;
2423 ret = snprintf(value + cursor, avail, "%s%d",
2424 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002425 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002426 if (ret < 0 || ret >= avail) {
2427 // if cursor is at the last element of the array
2428 // overwrite with \0 is duplicate work as
2429 // snprintf already put a \0 in place.
2430 // else
2431 // we had space to write the '|' at value[cursor]
2432 // (which will be overwritten) or no space to fill
2433 // the first element (=> cursor == 0)
2434 value[cursor] = '\0';
2435 break;
2436 }
2437 cursor += ret;
2438 ++i;
2439 }
2440 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2441 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002442 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002443 return ret >= 0;
2444}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002445
Haynes Mathew George569b7482017-05-08 14:44:27 -07002446static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2447{
2448 struct stream_out *out = (struct stream_out *)stream;
2449 struct str_parms *query = str_parms_create_str(keys);
2450 char *str;
2451 struct str_parms *reply = str_parms_create();
2452 bool replied = false;
2453 ALOGV("%s: enter: keys - %s", __func__, keys);
2454
2455 replied |= stream_get_parameter_channels(query, reply,
2456 &out->supported_channel_masks[0]);
2457 replied |= stream_get_parameter_formats(query, reply,
2458 &out->supported_formats[0]);
2459 replied |= stream_get_parameter_rates(query, reply,
2460 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002461 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 str = str_parms_to_str(reply);
2463 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002464 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 }
2466 str_parms_destroy(query);
2467 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002468 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 return str;
2470}
2471
2472static uint32_t out_get_latency(const struct audio_stream_out *stream)
2473{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002474 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 struct stream_out *out = (struct stream_out *)stream;
2476
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002477 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2478 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002479 else if ((out->realtime) ||
2480 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002481 // since the buffer won't be filled up faster than realtime,
2482 // return a smaller number
2483 period_ms = (out->af_period_multiplier * out->config.period_size *
2484 1000) / (out->config.rate);
2485 hw_delay = platform_render_latency(out->usecase)/1000;
2486 return period_ms + hw_delay;
2487 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002488
2489 return (out->config.period_count * out->config.period_size * 1000) /
2490 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491}
2492
2493static int out_set_volume(struct audio_stream_out *stream, float left,
2494 float right)
2495{
Eric Laurenta9024de2013-04-04 09:19:12 -07002496 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002497 int volume[2];
2498
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002499 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002500 /* only take left channel into account: the API is for stereo anyway */
2501 out->muted = (left == 0.0f);
2502 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002503 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2504 const char *mixer_ctl_name = "Compress Playback Volume";
2505 struct audio_device *adev = out->dev;
2506 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002507 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2508 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002509 /* try with the control based on device id */
2510 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2511 PCM_PLAYBACK);
2512 char ctl_name[128] = {0};
2513 snprintf(ctl_name, sizeof(ctl_name),
2514 "Compress Playback %d Volume", pcm_device_id);
2515 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2516 if (!ctl) {
2517 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2518 return -EINVAL;
2519 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002520 }
2521 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2522 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2523 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2524 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002525 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002526 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2527 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2528 if (!out->standby) {
2529 // if in standby, cached volume will be sent after stream is opened
2530 audio_extn_utils_send_app_type_gain(out->dev,
2531 out->app_type_cfg.app_type,
2532 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002533 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002534 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002535 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002536
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 return -ENOSYS;
2538}
2539
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002540// note: this call is safe only if the stream_cb is
2541// removed first in close_output_stream (as is done now).
2542static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2543{
2544 if (!stream || !parms)
2545 return;
2546
2547 struct stream_out *out = (struct stream_out *)stream;
2548 struct audio_device *adev = out->dev;
2549
2550 card_status_t status;
2551 int card;
2552 if (parse_snd_card_status(parms, &card, &status) < 0)
2553 return;
2554
2555 pthread_mutex_lock(&adev->lock);
2556 bool valid_cb = (card == adev->snd_card);
2557 pthread_mutex_unlock(&adev->lock);
2558
2559 if (!valid_cb)
2560 return;
2561
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002562 lock_output_stream(out);
2563 if (out->card_status != status)
2564 out->card_status = status;
2565 pthread_mutex_unlock(&out->lock);
2566
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002567 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2568 use_case_table[out->usecase],
2569 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2570
2571 if (status == CARD_STATUS_OFFLINE)
2572 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002573
2574 return;
2575}
2576
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002577#ifdef NO_AUDIO_OUT
2578static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002579 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002580{
2581 struct stream_out *out = (struct stream_out *)stream;
2582
2583 /* No Output device supported other than BT for playback.
2584 * Sleep for the amount of buffer duration
2585 */
Eric Laurenta1478072015-09-21 17:21:52 -07002586 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002587 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2588 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002589 out_get_sample_rate(&out->stream.common));
2590 pthread_mutex_unlock(&out->lock);
2591 return bytes;
2592}
2593#endif
2594
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2596 size_t bytes)
2597{
2598 struct stream_out *out = (struct stream_out *)stream;
2599 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002600 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002601 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602
Eric Laurenta1478072015-09-21 17:21:52 -07002603 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002604 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002605 const size_t frame_size = audio_stream_out_frame_size(stream);
2606 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002607
Eric Laurent0e46adf2016-12-16 12:49:24 -08002608 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2609 error_code = ERROR_CODE_WRITE;
2610 goto exit;
2611 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002613 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002614 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002616
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002617 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002619 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002620 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 goto exit;
2622 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002623
vivek mehta40125092017-08-21 18:48:51 -07002624 // after standby always force set last known cal step
2625 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2626 ALOGD("%s: retry previous failed cal level set", __func__);
2627 send_gain_dep_calibration_l();
2628 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002631 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002632 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002633 if (out->send_new_metadata) {
2634 ALOGVV("send new gapless metadata");
2635 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2636 out->send_new_metadata = 0;
2637 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002638 unsigned int avail;
2639 struct timespec tstamp;
2640 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2641 /* Do not limit write size if the available frames count is unknown */
2642 if (ret != 0) {
2643 avail = bytes;
2644 }
2645 if (avail == 0) {
2646 ret = 0;
2647 } else {
2648 if (avail > bytes) {
2649 avail = bytes;
2650 }
2651 ret = compress_write(out->compr, buffer, avail);
2652 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2653 __func__, avail, ret);
2654 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002655
Eric Laurent6e895242013-09-05 16:10:57 -07002656 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002657 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2658 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002659 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002660 compress_start(out->compr);
2661 out->playback_started = 1;
2662 out->offload_state = OFFLOAD_STATE_PLAYING;
2663 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002664 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002665 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002666 } else {
2667 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002668 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002669 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002670 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002671 return ret;
2672 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002673 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002674 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002675 size_t bytes_to_write = bytes;
2676
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002677 if (out->muted)
2678 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002679 // FIXME: this can be removed once audio flinger mixer supports mono output
2680 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
2681 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2682 int16_t *src = (int16_t *)buffer;
2683 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002684
Eric Laurentad2dde92017-09-20 18:27:31 -07002685 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2686 out->format != AUDIO_FORMAT_PCM_16_BIT,
2687 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002688
Eric Laurentad2dde92017-09-20 18:27:31 -07002689 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2690 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2691 }
2692 bytes_to_write /= 2;
2693 }
2694 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2695
2696 long ns = (frames * NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002697 request_out_focus(out, ns);
2698
2699 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2700 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002701 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002702 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002703 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002704
Haynes Mathew George03c40102016-01-29 17:57:48 -08002705 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002706 } else {
2707 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709 }
2710
2711exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002712 // For PCM we always consume the buffer and return #bytes regardless of ret.
2713 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002714 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002715 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002716 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002717
Andy Hung7401c7c2016-09-21 12:41:21 -07002718 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002719 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002720 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2721 ALOGE_IF(out->pcm != NULL,
2722 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002723 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002724 // usleep not guaranteed for values over 1 second but we don't limit here.
2725 }
2726 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 pthread_mutex_unlock(&out->lock);
2729
2730 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002731 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002732 if (sleeptime_us != 0)
2733 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734 }
2735 return bytes;
2736}
2737
2738static int out_get_render_position(const struct audio_stream_out *stream,
2739 uint32_t *dsp_frames)
2740{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002741 struct stream_out *out = (struct stream_out *)stream;
2742 *dsp_frames = 0;
2743 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002744 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002745 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002746 unsigned long frames = 0;
2747 // TODO: check return value
2748 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2749 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002750 ALOGVV("%s rendered frames %d sample_rate %d",
2751 __func__, *dsp_frames, out->sample_rate);
2752 }
2753 pthread_mutex_unlock(&out->lock);
2754 return 0;
2755 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002756 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757}
2758
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002759static int out_add_audio_effect(const struct audio_stream *stream __unused,
2760 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761{
2762 return 0;
2763}
2764
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002765static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2766 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767{
2768 return 0;
2769}
2770
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002771static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2772 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002774 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002775}
2776
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002777static int out_get_presentation_position(const struct audio_stream_out *stream,
2778 uint64_t *frames, struct timespec *timestamp)
2779{
2780 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002781 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002782 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002783
Eric Laurenta1478072015-09-21 17:21:52 -07002784 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002785
Eric Laurent949a0892013-09-20 09:20:13 -07002786 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2787 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002788 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002789 compress_get_tstamp(out->compr, &dsp_frames,
2790 &out->sample_rate);
2791 ALOGVV("%s rendered frames %ld sample_rate %d",
2792 __func__, dsp_frames, out->sample_rate);
2793 *frames = dsp_frames;
2794 ret = 0;
2795 /* this is the best we can do */
2796 clock_gettime(CLOCK_MONOTONIC, timestamp);
2797 }
2798 } else {
2799 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002800 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002801 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2802 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002803 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002804 // This adjustment accounts for buffering after app processor.
2805 // It is based on estimated DSP latency per use case, rather than exact.
2806 signed_frames -=
2807 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2808
Eric Laurent949a0892013-09-20 09:20:13 -07002809 // It would be unusual for this value to be negative, but check just in case ...
2810 if (signed_frames >= 0) {
2811 *frames = signed_frames;
2812 ret = 0;
2813 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002814 }
2815 }
2816 }
2817
2818 pthread_mutex_unlock(&out->lock);
2819
2820 return ret;
2821}
2822
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002823static int out_set_callback(struct audio_stream_out *stream,
2824 stream_callback_t callback, void *cookie)
2825{
2826 struct stream_out *out = (struct stream_out *)stream;
2827
2828 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002829 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002830 out->offload_callback = callback;
2831 out->offload_cookie = cookie;
2832 pthread_mutex_unlock(&out->lock);
2833 return 0;
2834}
2835
2836static int out_pause(struct audio_stream_out* stream)
2837{
2838 struct stream_out *out = (struct stream_out *)stream;
2839 int status = -ENOSYS;
2840 ALOGV("%s", __func__);
2841 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002842 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2844 status = compress_pause(out->compr);
2845 out->offload_state = OFFLOAD_STATE_PAUSED;
2846 }
2847 pthread_mutex_unlock(&out->lock);
2848 }
2849 return status;
2850}
2851
2852static int out_resume(struct audio_stream_out* stream)
2853{
2854 struct stream_out *out = (struct stream_out *)stream;
2855 int status = -ENOSYS;
2856 ALOGV("%s", __func__);
2857 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2858 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002859 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2861 status = compress_resume(out->compr);
2862 out->offload_state = OFFLOAD_STATE_PLAYING;
2863 }
2864 pthread_mutex_unlock(&out->lock);
2865 }
2866 return status;
2867}
2868
2869static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2870{
2871 struct stream_out *out = (struct stream_out *)stream;
2872 int status = -ENOSYS;
2873 ALOGV("%s", __func__);
2874 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002875 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002876 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2877 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2878 else
2879 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2880 pthread_mutex_unlock(&out->lock);
2881 }
2882 return status;
2883}
2884
2885static int out_flush(struct audio_stream_out* stream)
2886{
2887 struct stream_out *out = (struct stream_out *)stream;
2888 ALOGV("%s", __func__);
2889 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002890 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002891 stop_compressed_output_l(out);
2892 pthread_mutex_unlock(&out->lock);
2893 return 0;
2894 }
2895 return -ENOSYS;
2896}
2897
Eric Laurent0e46adf2016-12-16 12:49:24 -08002898static int out_stop(const struct audio_stream_out* stream)
2899{
2900 struct stream_out *out = (struct stream_out *)stream;
2901 struct audio_device *adev = out->dev;
2902 int ret = -ENOSYS;
2903
2904 ALOGV("%s", __func__);
2905 pthread_mutex_lock(&adev->lock);
2906 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2907 out->playback_started && out->pcm != NULL) {
2908 pcm_stop(out->pcm);
2909 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002910 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002911 }
2912 pthread_mutex_unlock(&adev->lock);
2913 return ret;
2914}
2915
2916static int out_start(const struct audio_stream_out* stream)
2917{
2918 struct stream_out *out = (struct stream_out *)stream;
2919 struct audio_device *adev = out->dev;
2920 int ret = -ENOSYS;
2921
2922 ALOGV("%s", __func__);
2923 pthread_mutex_lock(&adev->lock);
2924 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2925 !out->playback_started && out->pcm != NULL) {
2926 ret = start_output_stream(out);
2927 if (ret == 0) {
2928 out->playback_started = true;
2929 }
2930 }
2931 pthread_mutex_unlock(&adev->lock);
2932 return ret;
2933}
2934
Phil Burkbc991042017-02-24 08:06:44 -08002935/*
2936 * Modify config->period_count based on min_size_frames
2937 */
2938static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2939{
2940 int periodCountRequested = (min_size_frames + config->period_size - 1)
2941 / config->period_size;
2942 int periodCount = MMAP_PERIOD_COUNT_MIN;
2943
2944 ALOGV("%s original config.period_size = %d config.period_count = %d",
2945 __func__, config->period_size, config->period_count);
2946
2947 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2948 periodCount *= 2;
2949 }
2950 config->period_count = periodCount;
2951
2952 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2953}
2954
Eric Laurent0e46adf2016-12-16 12:49:24 -08002955static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2956 int32_t min_size_frames,
2957 struct audio_mmap_buffer_info *info)
2958{
2959 struct stream_out *out = (struct stream_out *)stream;
2960 struct audio_device *adev = out->dev;
2961 int ret = 0;
2962 unsigned int offset1;
2963 unsigned int frames1;
2964 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002965 uint32_t mmap_size;
2966 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002967
2968 ALOGV("%s", __func__);
2969 pthread_mutex_lock(&adev->lock);
2970
2971 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002972 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002973 ret = -EINVAL;
2974 goto exit;
2975 }
2976 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002977 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002978 ret = -ENOSYS;
2979 goto exit;
2980 }
2981 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2982 if (out->pcm_device_id < 0) {
2983 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2984 __func__, out->pcm_device_id, out->usecase);
2985 ret = -EINVAL;
2986 goto exit;
2987 }
Phil Burkbc991042017-02-24 08:06:44 -08002988
2989 adjust_mmap_period_count(&out->config, min_size_frames);
2990
Eric Laurent0e46adf2016-12-16 12:49:24 -08002991 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2992 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2993 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2994 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2995 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2996 step = "open";
2997 ret = -ENODEV;
2998 goto exit;
2999 }
3000 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3001 if (ret < 0) {
3002 step = "begin";
3003 goto exit;
3004 }
3005 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003006 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003007 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003008 ret = platform_get_mmap_data_fd(adev->platform,
3009 out->pcm_device_id, 0 /*playback*/,
3010 &info->shared_memory_fd,
3011 &mmap_size);
3012 if (ret < 0) {
3013 // Fall back to non exclusive mode
3014 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3015 } else {
3016 if (mmap_size < buffer_size) {
3017 step = "mmap";
3018 goto exit;
3019 }
3020 // FIXME: indicate exclusive mode support by returning a negative buffer size
3021 info->buffer_size_frames *= -1;
3022 }
3023 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003024
3025 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3026 if (ret < 0) {
3027 step = "commit";
3028 goto exit;
3029 }
Phil Burkbc991042017-02-24 08:06:44 -08003030
3031 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003032 ret = 0;
3033
3034 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3035 __func__, info->shared_memory_address, info->buffer_size_frames);
3036
3037exit:
3038 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003039 if (out->pcm == NULL) {
3040 ALOGE("%s: %s - %d", __func__, step, ret);
3041 } else {
3042 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003043 pcm_close(out->pcm);
3044 out->pcm = NULL;
3045 }
3046 }
3047 pthread_mutex_unlock(&adev->lock);
3048 return ret;
3049}
3050
3051static int out_get_mmap_position(const struct audio_stream_out *stream,
3052 struct audio_mmap_position *position)
3053{
3054 struct stream_out *out = (struct stream_out *)stream;
3055 ALOGVV("%s", __func__);
3056 if (position == NULL) {
3057 return -EINVAL;
3058 }
3059 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
3060 return -ENOSYS;
3061 }
3062 if (out->pcm == NULL) {
3063 return -ENOSYS;
3064 }
3065
3066 struct timespec ts = { 0, 0 };
3067 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
3068 if (ret < 0) {
3069 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3070 return ret;
3071 }
Andy Hungfc044e12017-03-20 09:24:22 -07003072 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003073 return 0;
3074}
3075
3076
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077/** audio_stream_in implementation **/
3078static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3079{
3080 struct stream_in *in = (struct stream_in *)stream;
3081
3082 return in->config.rate;
3083}
3084
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003085static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086{
3087 return -ENOSYS;
3088}
3089
3090static size_t in_get_buffer_size(const struct audio_stream *stream)
3091{
3092 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003093 return in->config.period_size * in->af_period_multiplier *
3094 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095}
3096
3097static uint32_t in_get_channels(const struct audio_stream *stream)
3098{
3099 struct stream_in *in = (struct stream_in *)stream;
3100
3101 return in->channel_mask;
3102}
3103
vivek mehta4ed66e62016-04-15 23:33:34 -07003104static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105{
vivek mehta4ed66e62016-04-15 23:33:34 -07003106 struct stream_in *in = (struct stream_in *)stream;
3107 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108}
3109
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003110static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111{
3112 return -ENOSYS;
3113}
3114
3115static int in_standby(struct audio_stream *stream)
3116{
3117 struct stream_in *in = (struct stream_in *)stream;
3118 struct audio_device *adev = in->dev;
3119 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003120 bool do_stop = true;
3121
Eric Laurent994a6932013-07-17 11:51:42 -07003122 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003123
3124 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003125
3126 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003127 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003128 audio_extn_sound_trigger_stop_lab(in);
3129 in->standby = true;
3130 }
3131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003133 if (adev->adm_deregister_stream)
3134 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3135
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003136 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003138 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003139 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003140 in->capture_started = false;
3141 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003142 if (in->pcm) {
3143 pcm_close(in->pcm);
3144 in->pcm = NULL;
3145 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003146 adev->enable_voicerx = false;
3147 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003148 if (do_stop) {
3149 status = stop_input_stream(in);
3150 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003151 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152 }
3153 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003154 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 return status;
3156}
3157
Andy Hungd13f0d32017-06-12 13:58:37 -07003158static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159{
Andy Hungd13f0d32017-06-12 13:58:37 -07003160 struct stream_in *in = (struct stream_in *)stream;
3161
3162 // We try to get the lock for consistency,
3163 // but it isn't necessary for these variables.
3164 // If we're not in standby, we may be blocked on a read.
3165 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3166 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3167 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3168 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3169
3170 if (locked) {
3171 pthread_mutex_unlock(&in->lock);
3172 }
3173
3174 // dump error info
3175 (void)error_log_dump(
3176 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177 return 0;
3178}
3179
3180static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3181{
3182 struct stream_in *in = (struct stream_in *)stream;
3183 struct audio_device *adev = in->dev;
3184 struct str_parms *parms;
3185 char *str;
3186 char value[32];
3187 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003188 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189
Eric Laurent994a6932013-07-17 11:51:42 -07003190 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191 parms = str_parms_create_str(kvpairs);
3192
3193 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3194
Eric Laurenta1478072015-09-21 17:21:52 -07003195 lock_input_stream(in);
3196
Eric Laurent150dbfe2013-02-27 14:31:02 -08003197 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 if (ret >= 0) {
3199 val = atoi(value);
3200 /* no audio source uses val == 0 */
3201 if ((in->source != val) && (val != 0)) {
3202 in->source = val;
3203 }
3204 }
3205
3206 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003208 if (ret >= 0) {
3209 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003210 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003211
3212 // Workaround: If routing to an non existing usb device, fail gracefully
3213 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003214 int card;
3215 if (audio_is_usb_in_device(val) &&
3216 (card = get_alive_usb_card(parms)) >= 0) {
3217
3218 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003219 status = -ENOSYS;
3220 } else {
3221
3222 in->device = val;
3223 /* If recording is in progress, change the tx device to new device */
3224 if (!in->standby) {
3225 ALOGV("update input routing change");
3226 // inform adm before actual routing to prevent glitches.
3227 if (adev->adm_on_routing_change) {
3228 adev->adm_on_routing_change(adev->adm_data,
3229 in->capture_handle);
3230 }
3231 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003232 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003233 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 }
3235 }
3236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003238 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239
3240 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003241 ALOGV("%s: exit: status(%d)", __func__, status);
3242 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243}
3244
Haynes Mathew George569b7482017-05-08 14:44:27 -07003245static char* in_get_parameters(const struct audio_stream *stream,
3246 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003248 struct stream_in *in = (struct stream_in *)stream;
3249 struct str_parms *query = str_parms_create_str(keys);
3250 char *str;
3251 struct str_parms *reply = str_parms_create();
3252 bool replied = false;
3253
3254 ALOGV("%s: enter: keys - %s", __func__, keys);
3255 replied |= stream_get_parameter_channels(query, reply,
3256 &in->supported_channel_masks[0]);
3257 replied |= stream_get_parameter_formats(query, reply,
3258 &in->supported_formats[0]);
3259 replied |= stream_get_parameter_rates(query, reply,
3260 &in->supported_sample_rates[0]);
3261 if (replied) {
3262 str = str_parms_to_str(reply);
3263 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003264 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003265 }
3266 str_parms_destroy(query);
3267 str_parms_destroy(reply);
3268 ALOGV("%s: exit: returns - %s", __func__, str);
3269 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270}
3271
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003272static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003274 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275}
3276
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003277static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3278{
3279 if (!stream || !parms)
3280 return;
3281
3282 struct stream_in *in = (struct stream_in *)stream;
3283 struct audio_device *adev = in->dev;
3284
3285 card_status_t status;
3286 int card;
3287 if (parse_snd_card_status(parms, &card, &status) < 0)
3288 return;
3289
3290 pthread_mutex_lock(&adev->lock);
3291 bool valid_cb = (card == adev->snd_card);
3292 pthread_mutex_unlock(&adev->lock);
3293
3294 if (!valid_cb)
3295 return;
3296
3297 lock_input_stream(in);
3298 if (in->card_status != status)
3299 in->card_status = status;
3300 pthread_mutex_unlock(&in->lock);
3301
3302 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3303 use_case_table[in->usecase],
3304 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3305
3306 // a better solution would be to report error back to AF and let
3307 // it put the stream to standby
3308 if (status == CARD_STATUS_OFFLINE)
3309 in_standby(&in->stream.common);
3310
3311 return;
3312}
3313
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3315 size_t bytes)
3316{
3317 struct stream_in *in = (struct stream_in *)stream;
3318 struct audio_device *adev = in->dev;
3319 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003320 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003321 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322
Eric Laurenta1478072015-09-21 17:21:52 -07003323 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003324 const size_t frame_size = audio_stream_in_frame_size(stream);
3325 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003326
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003327 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003328 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003329 /* Read from sound trigger HAL */
3330 audio_extn_sound_trigger_read(in, buffer, bytes);
3331 pthread_mutex_unlock(&in->lock);
3332 return bytes;
3333 }
3334
Eric Laurent0e46adf2016-12-16 12:49:24 -08003335 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3336 ret = -ENOSYS;
3337 goto exit;
3338 }
3339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003340 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003341 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003343 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345 goto exit;
3346 }
3347 in->standby = 0;
3348 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349
Andy Hungd13f0d32017-06-12 13:58:37 -07003350 // errors that occur here are read errors.
3351 error_code = ERROR_CODE_READ;
3352
Haynes Mathew George03c40102016-01-29 17:57:48 -08003353 //what's the duration requested by the client?
3354 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3355 in->config.rate;
3356 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003357
Haynes Mathew George03c40102016-01-29 17:57:48 -08003358 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003360 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003361 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003362 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003363 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003364 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003365 if (ret < 0) {
3366 ALOGE("Failed to read w/err %s", strerror(errno));
3367 ret = -errno;
3368 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003369 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3370 if (bytes % 4 == 0) {
3371 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3372 int_buf_stream = buffer;
3373 for (size_t itt=0; itt < bytes/4 ; itt++) {
3374 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003375 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003376 } else {
3377 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3378 ret = -EINVAL;
3379 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003380 }
3381 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 }
3383
Haynes Mathew George03c40102016-01-29 17:57:48 -08003384 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 /*
3387 * Instead of writing zeroes here, we could trust the hardware
3388 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003389 * 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 -08003390 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003391 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003393 in->frames_muted += frames;
3394 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395
3396exit:
3397 pthread_mutex_unlock(&in->lock);
3398
3399 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003400 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003401 in_standby(&in->stream.common);
3402 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003403 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003404 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003405 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003406 }
3407 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003408 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409 }
3410 return bytes;
3411}
3412
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003413static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003414{
3415 return 0;
3416}
3417
Andy Hung6ebe5962016-01-15 17:46:57 -08003418static int in_get_capture_position(const struct audio_stream_in *stream,
3419 int64_t *frames, int64_t *time)
3420{
3421 if (stream == NULL || frames == NULL || time == NULL) {
3422 return -EINVAL;
3423 }
3424 struct stream_in *in = (struct stream_in *)stream;
3425 int ret = -ENOSYS;
3426
3427 lock_input_stream(in);
3428 if (in->pcm) {
3429 struct timespec timestamp;
3430 unsigned int avail;
3431 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3432 *frames = in->frames_read + avail;
3433 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3434 ret = 0;
3435 }
3436 }
3437 pthread_mutex_unlock(&in->lock);
3438 return ret;
3439}
3440
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003441static int add_remove_audio_effect(const struct audio_stream *stream,
3442 effect_handle_t effect,
3443 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003445 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003446 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003447 int status = 0;
3448 effect_descriptor_t desc;
3449
3450 status = (*effect)->get_descriptor(effect, &desc);
3451 if (status != 0)
3452 return status;
3453
Eric Laurenta1478072015-09-21 17:21:52 -07003454 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003455 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003456 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003457 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003458 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003459 in->enable_aec != enable &&
3460 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3461 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003462 if (!enable)
3463 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003464 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3465 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3466 adev->enable_voicerx = enable;
3467 struct audio_usecase *usecase;
3468 struct listnode *node;
3469 list_for_each(node, &adev->usecase_list) {
3470 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003471 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003472 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003473 }
3474 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003475 if (!in->standby)
3476 select_devices(in->dev, in->usecase);
3477 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003478 if (in->enable_ns != enable &&
3479 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3480 in->enable_ns = enable;
3481 if (!in->standby)
3482 select_devices(in->dev, in->usecase);
3483 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003484 pthread_mutex_unlock(&in->dev->lock);
3485 pthread_mutex_unlock(&in->lock);
3486
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487 return 0;
3488}
3489
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003490static int in_add_audio_effect(const struct audio_stream *stream,
3491 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492{
Eric Laurent994a6932013-07-17 11:51:42 -07003493 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003494 return add_remove_audio_effect(stream, effect, true);
3495}
3496
3497static int in_remove_audio_effect(const struct audio_stream *stream,
3498 effect_handle_t effect)
3499{
Eric Laurent994a6932013-07-17 11:51:42 -07003500 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003501 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003502}
3503
Eric Laurent0e46adf2016-12-16 12:49:24 -08003504static int in_stop(const struct audio_stream_in* stream)
3505{
3506 struct stream_in *in = (struct stream_in *)stream;
3507 struct audio_device *adev = in->dev;
3508
3509 int ret = -ENOSYS;
3510 ALOGV("%s", __func__);
3511 pthread_mutex_lock(&adev->lock);
3512 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3513 in->capture_started && in->pcm != NULL) {
3514 pcm_stop(in->pcm);
3515 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003516 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003517 }
3518 pthread_mutex_unlock(&adev->lock);
3519 return ret;
3520}
3521
3522static int in_start(const struct audio_stream_in* stream)
3523{
3524 struct stream_in *in = (struct stream_in *)stream;
3525 struct audio_device *adev = in->dev;
3526 int ret = -ENOSYS;
3527
3528 ALOGV("%s in %p", __func__, in);
3529 pthread_mutex_lock(&adev->lock);
3530 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3531 !in->capture_started && in->pcm != NULL) {
3532 if (!in->capture_started) {
3533 ret = start_input_stream(in);
3534 if (ret == 0) {
3535 in->capture_started = true;
3536 }
3537 }
3538 }
3539 pthread_mutex_unlock(&adev->lock);
3540 return ret;
3541}
3542
3543static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3544 int32_t min_size_frames,
3545 struct audio_mmap_buffer_info *info)
3546{
3547 struct stream_in *in = (struct stream_in *)stream;
3548 struct audio_device *adev = in->dev;
3549 int ret = 0;
3550 unsigned int offset1;
3551 unsigned int frames1;
3552 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003553 uint32_t mmap_size;
3554 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003555
3556 pthread_mutex_lock(&adev->lock);
3557 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003558
Eric Laurent0e46adf2016-12-16 12:49:24 -08003559 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003560 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003561 ret = -EINVAL;
3562 goto exit;
3563 }
3564 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003565 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003566 ALOGV("%s in %p", __func__, in);
3567 ret = -ENOSYS;
3568 goto exit;
3569 }
3570 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3571 if (in->pcm_device_id < 0) {
3572 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3573 __func__, in->pcm_device_id, in->usecase);
3574 ret = -EINVAL;
3575 goto exit;
3576 }
Phil Burkbc991042017-02-24 08:06:44 -08003577
3578 adjust_mmap_period_count(&in->config, min_size_frames);
3579
Eric Laurent0e46adf2016-12-16 12:49:24 -08003580 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3581 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3582 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3583 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3584 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3585 step = "open";
3586 ret = -ENODEV;
3587 goto exit;
3588 }
3589
3590 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3591 if (ret < 0) {
3592 step = "begin";
3593 goto exit;
3594 }
3595 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003596 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003597 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003598 ret = platform_get_mmap_data_fd(adev->platform,
3599 in->pcm_device_id, 1 /*capture*/,
3600 &info->shared_memory_fd,
3601 &mmap_size);
3602 if (ret < 0) {
3603 // Fall back to non exclusive mode
3604 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3605 } else {
3606 if (mmap_size < buffer_size) {
3607 step = "mmap";
3608 goto exit;
3609 }
3610 // FIXME: indicate exclusive mode support by returning a negative buffer size
3611 info->buffer_size_frames *= -1;
3612 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003613
Haynes Mathew George96483a22017-03-28 14:52:47 -07003614 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003615
3616 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3617 if (ret < 0) {
3618 step = "commit";
3619 goto exit;
3620 }
3621
Phil Burkbc991042017-02-24 08:06:44 -08003622 in->standby = false;
3623 ret = 0;
3624
Eric Laurent0e46adf2016-12-16 12:49:24 -08003625 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3626 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003627
3628exit:
3629 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003630 if (in->pcm == NULL) {
3631 ALOGE("%s: %s - %d", __func__, step, ret);
3632 } else {
3633 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003634 pcm_close(in->pcm);
3635 in->pcm = NULL;
3636 }
3637 }
3638 pthread_mutex_unlock(&adev->lock);
3639 return ret;
3640}
3641
3642static int in_get_mmap_position(const struct audio_stream_in *stream,
3643 struct audio_mmap_position *position)
3644{
3645 struct stream_in *in = (struct stream_in *)stream;
3646 ALOGVV("%s", __func__);
3647 if (position == NULL) {
3648 return -EINVAL;
3649 }
3650 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3651 return -ENOSYS;
3652 }
3653 if (in->pcm == NULL) {
3654 return -ENOSYS;
3655 }
3656 struct timespec ts = { 0, 0 };
3657 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3658 if (ret < 0) {
3659 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3660 return ret;
3661 }
Andy Hungfc044e12017-03-20 09:24:22 -07003662 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003663 return 0;
3664}
3665
3666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667static int adev_open_output_stream(struct audio_hw_device *dev,
3668 audio_io_handle_t handle,
3669 audio_devices_t devices,
3670 audio_output_flags_t flags,
3671 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003672 struct audio_stream_out **stream_out,
3673 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674{
3675 struct audio_device *adev = (struct audio_device *)dev;
3676 struct stream_out *out;
3677 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003678 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3679 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3680 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3681 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682
Andy Hungd9653bd2017-08-01 19:31:39 -07003683 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3684 return -ENOSYS;
3685 }
3686
Eric Laurent994a6932013-07-17 11:51:42 -07003687 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003688 __func__, config->sample_rate, config->channel_mask, devices, flags);
3689 *stream_out = NULL;
3690 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3691
3692 if (devices == AUDIO_DEVICE_NONE)
3693 devices = AUDIO_DEVICE_OUT_SPEAKER;
3694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003695 out->flags = flags;
3696 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003697 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003698 out->format = config->format;
3699 out->sample_rate = config->sample_rate;
3700 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3701 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003702 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703
3704 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003705 if (audio_is_linear_pcm(out->format) &&
3706 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003707 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003708 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003709 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003710 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003711 if (config->sample_rate == 0)
3712 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3713 if (config->channel_mask == 0)
3714 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3715 if (config->format == AUDIO_FORMAT_DEFAULT)
3716 config->format = AUDIO_FORMAT_PCM_16_BIT;
3717 } else if (is_usb_dev) {
3718 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3719 &config->format,
3720 &out->supported_formats[0],
3721 MAX_SUPPORTED_FORMATS,
3722 &config->channel_mask,
3723 &out->supported_channel_masks[0],
3724 MAX_SUPPORTED_CHANNEL_MASKS,
3725 &config->sample_rate,
3726 &out->supported_sample_rates[0],
3727 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003728 ALOGV("plugged dev USB ret %d", ret);
3729 } else {
3730 ret = -1;
3731 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003732 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003733 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003734 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003735
Haynes Mathew George569b7482017-05-08 14:44:27 -07003736 out->channel_mask = config->channel_mask;
3737 out->sample_rate = config->sample_rate;
3738 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003739 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3740 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003741 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003743 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003744 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3745 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003746 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003747 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003748 pthread_mutex_lock(&adev->lock);
3749 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3750 pthread_mutex_unlock(&adev->lock);
3751
3752 // reject offload during card offline to allow
3753 // fallback to s/w paths
3754 if (offline) {
3755 ret = -ENODEV;
3756 goto error_open;
3757 }
3758
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003759 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3760 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3761 ALOGE("%s: Unsupported Offload information", __func__);
3762 ret = -EINVAL;
3763 goto error_open;
3764 }
3765 if (!is_supported_format(config->offload_info.format)) {
3766 ALOGE("%s: Unsupported audio format", __func__);
3767 ret = -EINVAL;
3768 goto error_open;
3769 }
3770
3771 out->compr_config.codec = (struct snd_codec *)
3772 calloc(1, sizeof(struct snd_codec));
3773
3774 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3775 if (config->offload_info.channel_mask)
3776 out->channel_mask = config->offload_info.channel_mask;
3777 else if (config->channel_mask)
3778 out->channel_mask = config->channel_mask;
3779 out->format = config->offload_info.format;
3780 out->sample_rate = config->offload_info.sample_rate;
3781
3782 out->stream.set_callback = out_set_callback;
3783 out->stream.pause = out_pause;
3784 out->stream.resume = out_resume;
3785 out->stream.drain = out_drain;
3786 out->stream.flush = out_flush;
3787
3788 out->compr_config.codec->id =
3789 get_snd_codec_id(config->offload_info.format);
3790 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3791 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003792 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003793 out->compr_config.codec->bit_rate =
3794 config->offload_info.bit_rate;
3795 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003796 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003797 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3798
3799 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3800 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003801
3802 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003803 create_offload_callback_thread(out);
3804 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3805 __func__, config->offload_info.version,
3806 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003807 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003808 switch (config->sample_rate) {
3809 case 8000:
3810 case 16000:
3811 case 48000:
3812 out->sample_rate = config->sample_rate;
3813 break;
3814 default:
3815 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003816 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003817 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003818 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3819 out->config = pcm_config_afe_proxy_playback;
3820 adev->voice_tx_output = out;
Eric Laurentad2dde92017-09-20 18:27:31 -07003821 } else if (out->flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
3822 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
vivek mehtaa68fea62017-06-08 19:04:02 -07003823 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07003824 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3825 out->config = pcm_config_voip;
3826 out->config.format = pcm_format_from_audio_format(config->format);
3827 out->config.rate = config->sample_rate;
vivek mehtaa68fea62017-06-08 19:04:02 -07003828 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3829 config->sample_rate,
3830 config->format,
3831 out->config.channels,
3832 false /*is_low_latency*/);
3833 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3834 out->config.period_size = buffer_size / frame_size;
3835 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3836 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003838 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3839 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3840 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003841 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3842 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3843 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003844 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3845 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003846 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003847 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003848 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3849 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3850 out->config = pcm_config_mmap_playback;
3851 out->stream.start = out_start;
3852 out->stream.stop = out_stop;
3853 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3854 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003855 } else {
3856 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3857 out->config = pcm_config_low_latency;
3858 }
3859 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003860 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003861 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003862 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003864
3865 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3866 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3867 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3868 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3869 __func__, config->sample_rate, config->format, config->channel_mask);
3870 config->sample_rate = out->sample_rate;
3871 config->format = out->format;
3872 config->channel_mask = out->channel_mask;
3873 ret = -EINVAL;
3874 goto error_open;
3875 }
3876
Andy Hung6fcba9c2014-03-18 11:53:32 -07003877 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3878 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003880 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003881 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003882 adev->primary_output = out;
3883 else {
3884 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003885 ret = -EEXIST;
3886 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003887 }
3888 }
3889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890 /* Check if this usecase is already existing */
3891 pthread_mutex_lock(&adev->lock);
3892 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3893 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003895 ret = -EEXIST;
3896 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 }
3898 pthread_mutex_unlock(&adev->lock);
3899
3900 out->stream.common.get_sample_rate = out_get_sample_rate;
3901 out->stream.common.set_sample_rate = out_set_sample_rate;
3902 out->stream.common.get_buffer_size = out_get_buffer_size;
3903 out->stream.common.get_channels = out_get_channels;
3904 out->stream.common.get_format = out_get_format;
3905 out->stream.common.set_format = out_set_format;
3906 out->stream.common.standby = out_standby;
3907 out->stream.common.dump = out_dump;
3908 out->stream.common.set_parameters = out_set_parameters;
3909 out->stream.common.get_parameters = out_get_parameters;
3910 out->stream.common.add_audio_effect = out_add_audio_effect;
3911 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3912 out->stream.get_latency = out_get_latency;
3913 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003914#ifdef NO_AUDIO_OUT
3915 out->stream.write = out_write_for_no_output;
3916#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003917 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003918#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919 out->stream.get_render_position = out_get_render_position;
3920 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003921 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922
Eric Laurent0e46adf2016-12-16 12:49:24 -08003923 if (out->realtime)
3924 out->af_period_multiplier = af_period_multiplier;
3925 else
3926 out->af_period_multiplier = 1;
3927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003929 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003930 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003932 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003933 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003934 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936 config->format = out->stream.common.get_format(&out->stream.common);
3937 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3938 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3939
Andy Hunga452b0a2017-03-15 14:51:15 -07003940 out->error_log = error_log_create(
3941 ERROR_LOG_ENTRIES,
3942 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3943
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003944 /*
3945 By locking output stream before registering, we allow the callback
3946 to update stream's state only after stream's initial state is set to
3947 adev state.
3948 */
3949 lock_output_stream(out);
3950 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3951 pthread_mutex_lock(&adev->lock);
3952 out->card_status = adev->card_status;
3953 pthread_mutex_unlock(&adev->lock);
3954 pthread_mutex_unlock(&out->lock);
3955
vivek mehta4a824772017-06-08 19:05:49 -07003956 stream_app_type_cfg_init(&out->app_type_cfg);
3957
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003958 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003959
Eric Laurent994a6932013-07-17 11:51:42 -07003960 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003962
3963error_open:
3964 free(out);
3965 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003966 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003967 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003968}
3969
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003970static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971 struct audio_stream_out *stream)
3972{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003973 struct stream_out *out = (struct stream_out *)stream;
3974 struct audio_device *adev = out->dev;
3975
Eric Laurent994a6932013-07-17 11:51:42 -07003976 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003977
3978 // must deregister from sndmonitor first to prevent races
3979 // between the callback and close_stream
3980 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003982 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3983 destroy_offload_callback_thread(out);
3984
3985 if (out->compr_config.codec != NULL)
3986 free(out->compr_config.codec);
3987 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003988
3989 if (adev->voice_tx_output == out)
3990 adev->voice_tx_output = NULL;
3991
Andy Hunga452b0a2017-03-15 14:51:15 -07003992 error_log_destroy(out->error_log);
3993 out->error_log = NULL;
3994
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003995 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07003996 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003997 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003999 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000}
4001
4002static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4003{
4004 struct audio_device *adev = (struct audio_device *)dev;
4005 struct str_parms *parms;
4006 char *str;
4007 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004008 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004009 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004010 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011
Joe Onorato188b6222016-03-01 11:02:27 -08004012 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004013
4014 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004015
4016 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004017 status = voice_set_parameters(adev, parms);
4018 if (status != 0) {
4019 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004020 }
4021
4022 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4023 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004024 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004025 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4026 adev->bluetooth_nrec = true;
4027 else
4028 adev->bluetooth_nrec = false;
4029 }
4030
4031 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4032 if (ret >= 0) {
4033 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4034 adev->screen_off = false;
4035 else
4036 adev->screen_off = true;
4037 }
4038
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004039 ret = str_parms_get_int(parms, "rotation", &val);
4040 if (ret >= 0) {
4041 bool reverse_speakers = false;
4042 switch(val) {
4043 // FIXME: note that the code below assumes that the speakers are in the correct placement
4044 // relative to the user when the device is rotated 90deg from its default rotation. This
4045 // assumption is device-specific, not platform-specific like this code.
4046 case 270:
4047 reverse_speakers = true;
4048 break;
4049 case 0:
4050 case 90:
4051 case 180:
4052 break;
4053 default:
4054 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004055 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004056 }
Eric Laurent03f09432014-03-25 18:09:11 -07004057 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004058 // check and set swap
4059 // - check if orientation changed and speaker active
4060 // - set rotation and cache the rotation value
4061 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004062 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004063 }
4064
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004065 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4066 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004067 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004068 }
4069
David Linee3fe402017-03-13 10:00:42 -07004070 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4071 if (ret >= 0) {
4072 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004073 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004074 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4075 if (ret >= 0) {
4076 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004077 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004078 }
Eric Laurent99dab492017-06-17 15:19:08 -07004079 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004080 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4081 if (ret >= 0) {
4082 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004083 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004084 }
4085 }
4086 }
4087
4088 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4089 if (ret >= 0) {
4090 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004091 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004092 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4093 if (ret >= 0) {
4094 const int card = atoi(value);
4095
Eric Laurent99dab492017-06-17 15:19:08 -07004096 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004097 }
Eric Laurent99dab492017-06-17 15:19:08 -07004098 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004099 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4100 if (ret >= 0) {
4101 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004102 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004103 }
4104 }
4105 }
4106
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004107 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004108done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004110 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004111 ALOGV("%s: exit with code(%d)", __func__, status);
4112 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113}
4114
4115static char* adev_get_parameters(const struct audio_hw_device *dev,
4116 const char *keys)
4117{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004118 struct audio_device *adev = (struct audio_device *)dev;
4119 struct str_parms *reply = str_parms_create();
4120 struct str_parms *query = str_parms_create_str(keys);
4121 char *str;
4122
4123 pthread_mutex_lock(&adev->lock);
4124
4125 voice_get_parameters(adev, query, reply);
4126 str = str_parms_to_str(reply);
4127 str_parms_destroy(query);
4128 str_parms_destroy(reply);
4129
4130 pthread_mutex_unlock(&adev->lock);
4131 ALOGV("%s: exit: returns - %s", __func__, str);
4132 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133}
4134
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004135static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136{
4137 return 0;
4138}
4139
Haynes Mathew George5191a852013-09-11 14:19:36 -07004140static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4141{
4142 int ret;
4143 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004144
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004145 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4146
Haynes Mathew George5191a852013-09-11 14:19:36 -07004147 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004148 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004149 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004150
Haynes Mathew George5191a852013-09-11 14:19:36 -07004151 return ret;
4152}
4153
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004154static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155{
4156 return -ENOSYS;
4157}
4158
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004159static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4160 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161{
4162 return -ENOSYS;
4163}
4164
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004165static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166{
4167 return -ENOSYS;
4168}
4169
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004170static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171{
4172 return -ENOSYS;
4173}
4174
4175static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4176{
4177 struct audio_device *adev = (struct audio_device *)dev;
4178
4179 pthread_mutex_lock(&adev->lock);
4180 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004181 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004183 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4184 voice_is_in_call(adev)) {
4185 voice_stop_call(adev);
4186 adev->current_call_output = NULL;
4187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188 }
4189 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004190
4191 audio_extn_extspk_set_mode(adev->extspk, mode);
4192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193 return 0;
4194}
4195
4196static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4197{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004198 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004200
Eric Laurent2bafff12016-03-17 12:17:23 -07004201 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004202 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004203 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4204 ret = audio_extn_hfp_set_mic_mute(adev, state);
4205 } else {
4206 ret = voice_set_mic_mute(adev, state);
4207 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004208 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004209 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004210
4211 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212}
4213
4214static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4215{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004216 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217 return 0;
4218}
4219
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004220static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004221 const struct audio_config *config)
4222{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004223 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004224
Eric Laurent74b55762017-07-09 17:04:53 -07004225 /* Don't know if USB HIFI in this context so use true to be conservative */
4226 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4227 true /*is_usb_hifi */) != 0)
4228 return 0;
4229
vivek mehtaa68fea62017-06-08 19:04:02 -07004230 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4231 config->sample_rate, config->format,
4232 channel_count,
4233 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004234}
4235
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004236static bool adev_input_allow_hifi_record(struct audio_device *adev,
4237 audio_devices_t devices,
4238 audio_input_flags_t flags,
4239 audio_source_t source) {
4240 const bool allowed = true;
4241
4242 if (!audio_is_usb_in_device(devices))
4243 return !allowed;
4244
4245 switch (flags) {
4246 case AUDIO_INPUT_FLAG_NONE:
4247 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4248 break;
4249 default:
4250 return !allowed;
4251 }
4252
4253 switch (source) {
4254 case AUDIO_SOURCE_DEFAULT:
4255 case AUDIO_SOURCE_MIC:
4256 case AUDIO_SOURCE_UNPROCESSED:
4257 break;
4258 default:
4259 return !allowed;
4260 }
4261
4262 switch (adev->mode) {
4263 case 0:
4264 break;
4265 default:
4266 return !allowed;
4267 }
4268
4269 return allowed;
4270}
4271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004272static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004273 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274 audio_devices_t devices,
4275 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004276 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004277 audio_input_flags_t flags,
4278 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004279 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280{
4281 struct audio_device *adev = (struct audio_device *)dev;
4282 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004283 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004284 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004285 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004286 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004287 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4288 devices,
4289 flags,
4290 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004291 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004292 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004293
Andy Hungd9653bd2017-08-01 19:31:39 -07004294 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4295 return -ENOSYS;
4296 }
4297
Eric Laurent74b55762017-07-09 17:04:53 -07004298 if (!(is_usb_dev && may_use_hifi_record)) {
4299 if (config->sample_rate == 0)
4300 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4301 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4302 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4303 if (config->format == AUDIO_FORMAT_DEFAULT)
4304 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004305
Eric Laurent74b55762017-07-09 17:04:53 -07004306 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4307
4308 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4309 return -EINVAL;
4310 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004312 if (audio_extn_tfa_98xx_is_supported() &&
4313 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004314 return -EINVAL;
4315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4317
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004318 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004319 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321 in->stream.common.get_sample_rate = in_get_sample_rate;
4322 in->stream.common.set_sample_rate = in_set_sample_rate;
4323 in->stream.common.get_buffer_size = in_get_buffer_size;
4324 in->stream.common.get_channels = in_get_channels;
4325 in->stream.common.get_format = in_get_format;
4326 in->stream.common.set_format = in_set_format;
4327 in->stream.common.standby = in_standby;
4328 in->stream.common.dump = in_dump;
4329 in->stream.common.set_parameters = in_set_parameters;
4330 in->stream.common.get_parameters = in_get_parameters;
4331 in->stream.common.add_audio_effect = in_add_audio_effect;
4332 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4333 in->stream.set_gain = in_set_gain;
4334 in->stream.read = in_read;
4335 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004336 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337
4338 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004339 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004340 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004342 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004343 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344
Haynes Mathew George569b7482017-05-08 14:44:27 -07004345 if (is_usb_dev && may_use_hifi_record) {
4346 /* HiFi record selects an appropriate format, channel, rate combo
4347 depending on sink capabilities*/
4348 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4349 &config->format,
4350 &in->supported_formats[0],
4351 MAX_SUPPORTED_FORMATS,
4352 &config->channel_mask,
4353 &in->supported_channel_masks[0],
4354 MAX_SUPPORTED_CHANNEL_MASKS,
4355 &config->sample_rate,
4356 &in->supported_sample_rates[0],
4357 MAX_SUPPORTED_SAMPLE_RATES);
4358 if (ret != 0) {
4359 ret = -EINVAL;
4360 goto err_open;
4361 }
Eric Laurent74b55762017-07-09 17:04:53 -07004362 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004363 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004364 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004365 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4366 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4367 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4368 bool ret_error = false;
4369 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4370 from HAL is 8_24
4371 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4372 8_24 return error indicating supported format is 8_24
4373 *> In case of any other source requesting 24 bit or float return error
4374 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004375
vivek mehta57ff9b52016-04-28 14:13:08 -07004376 on error flinger will retry with supported format passed
4377 */
4378 if (source != AUDIO_SOURCE_UNPROCESSED) {
4379 config->format = AUDIO_FORMAT_PCM_16_BIT;
4380 ret_error = true;
4381 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4382 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4383 ret_error = true;
4384 }
4385
4386 if (ret_error) {
4387 ret = -EINVAL;
4388 goto err_open;
4389 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004390 }
4391
vivek mehta57ff9b52016-04-28 14:13:08 -07004392 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004393 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004394
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004396 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4397 if (config->sample_rate == 0)
4398 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4399 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4400 config->sample_rate != 8000) {
4401 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4402 ret = -EINVAL;
4403 goto err_open;
4404 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004405
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004406 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4407 config->format = AUDIO_FORMAT_PCM_16_BIT;
4408 ret = -EINVAL;
4409 goto err_open;
4410 }
4411
4412 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4413 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004414 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004415 } else if (is_usb_dev && may_use_hifi_record) {
4416 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4417 in->config = pcm_config_audio_capture;
4418 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004419 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4420 config->sample_rate,
4421 config->format,
4422 channel_count,
4423 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004424 in->config.period_size = buffer_size / frame_size;
4425 in->config.rate = config->sample_rate;
4426 in->af_period_multiplier = 1;
4427 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004428 } else {
4429 in->usecase = USECASE_AUDIO_RECORD;
4430 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004431 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004432 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004433#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004434 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004435#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004436 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004437 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004438 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004439 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004440 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4441 config->sample_rate,
4442 config->format,
4443 channel_count,
4444 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004445 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004446 in->config.rate = config->sample_rate;
4447 in->af_period_multiplier = 1;
4448 } else {
4449 // period size is left untouched for rt mode playback
4450 in->config = pcm_config_audio_capture_rt;
4451 in->af_period_multiplier = af_period_multiplier;
4452 }
4453 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4454 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004455 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004456 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4457 in->config = pcm_config_mmap_capture;
4458 in->stream.start = in_start;
4459 in->stream.stop = in_stop;
4460 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4461 in->stream.get_mmap_position = in_get_mmap_position;
4462 in->af_period_multiplier = 1;
4463 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004464 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004465 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004466 (config->sample_rate == 8000 ||
4467 config->sample_rate == 16000 ||
4468 config->sample_rate == 32000 ||
4469 config->sample_rate == 48000) &&
4470 channel_count == 1) {
4471 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4472 in->config = pcm_config_audio_capture;
4473 frame_size = audio_stream_in_frame_size(&in->stream);
4474 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4475 config->sample_rate,
4476 config->format,
4477 channel_count, false /*is_low_latency*/);
4478 in->config.period_size = buffer_size / frame_size;
4479 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4480 in->config.rate = config->sample_rate;
4481 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004482 } else {
4483 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004484 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004485 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4486 config->sample_rate,
4487 config->format,
4488 channel_count,
4489 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004490 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004491 in->config.rate = config->sample_rate;
4492 in->af_period_multiplier = 1;
4493 }
4494 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4495 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004496 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004497
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004498 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004499 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500
Andy Hungd13f0d32017-06-12 13:58:37 -07004501 in->error_log = error_log_create(
4502 ERROR_LOG_ENTRIES,
4503 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4504
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004505 /* This stream could be for sound trigger lab,
4506 get sound trigger pcm if present */
4507 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004508
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004509 lock_input_stream(in);
4510 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4511 pthread_mutex_lock(&adev->lock);
4512 in->card_status = adev->card_status;
4513 pthread_mutex_unlock(&adev->lock);
4514 pthread_mutex_unlock(&in->lock);
4515
vivek mehta4a824772017-06-08 19:05:49 -07004516 stream_app_type_cfg_init(&in->app_type_cfg);
4517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004518 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004519 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520 return 0;
4521
4522err_open:
4523 free(in);
4524 *stream_in = NULL;
4525 return ret;
4526}
4527
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004528static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004529 struct audio_stream_in *stream)
4530{
Andy Hungd13f0d32017-06-12 13:58:37 -07004531 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004532 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004533
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004534 // must deregister from sndmonitor first to prevent races
4535 // between the callback and close_stream
4536 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004537 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004538
4539 error_log_destroy(in->error_log);
4540 in->error_log = NULL;
4541
Andy Hung0dbb52b2017-08-09 13:51:38 -07004542 pthread_mutex_destroy(&in->pre_lock);
4543 pthread_mutex_destroy(&in->lock);
4544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004545 free(stream);
4546
4547 return;
4548}
4549
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004550static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004551{
4552 return 0;
4553}
4554
Andy Hung31aca912014-03-20 17:14:59 -07004555/* verifies input and output devices and their capabilities.
4556 *
4557 * This verification is required when enabling extended bit-depth or
4558 * sampling rates, as not all qcom products support it.
4559 *
4560 * Suitable for calling only on initialization such as adev_open().
4561 * It fills the audio_device use_case_table[] array.
4562 *
4563 * Has a side-effect that it needs to configure audio routing / devices
4564 * in order to power up the devices and read the device parameters.
4565 * It does not acquire any hw device lock. Should restore the devices
4566 * back to "normal state" upon completion.
4567 */
4568static int adev_verify_devices(struct audio_device *adev)
4569{
4570 /* enumeration is a bit difficult because one really wants to pull
4571 * the use_case, device id, etc from the hidden pcm_device_table[].
4572 * In this case there are the following use cases and device ids.
4573 *
4574 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4575 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004576 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004577 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4578 * [USECASE_AUDIO_RECORD] = {0, 0},
4579 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4580 * [USECASE_VOICE_CALL] = {2, 2},
4581 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004582 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004583 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4584 */
4585
4586 /* should be the usecases enabled in adev_open_input_stream() */
4587 static const int test_in_usecases[] = {
4588 USECASE_AUDIO_RECORD,
4589 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4590 };
4591 /* should be the usecases enabled in adev_open_output_stream()*/
4592 static const int test_out_usecases[] = {
4593 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4594 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4595 };
4596 static const usecase_type_t usecase_type_by_dir[] = {
4597 PCM_PLAYBACK,
4598 PCM_CAPTURE,
4599 };
4600 static const unsigned flags_by_dir[] = {
4601 PCM_OUT,
4602 PCM_IN,
4603 };
4604
4605 size_t i;
4606 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004607 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004608 char info[512]; /* for possible debug info */
4609
4610 for (dir = 0; dir < 2; ++dir) {
4611 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4612 const unsigned flags_dir = flags_by_dir[dir];
4613 const size_t testsize =
4614 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4615 const int *testcases =
4616 dir ? test_in_usecases : test_out_usecases;
4617 const audio_devices_t audio_device =
4618 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4619
4620 for (i = 0; i < testsize; ++i) {
4621 const audio_usecase_t audio_usecase = testcases[i];
4622 int device_id;
4623 snd_device_t snd_device;
4624 struct pcm_params **pparams;
4625 struct stream_out out;
4626 struct stream_in in;
4627 struct audio_usecase uc_info;
4628 int retval;
4629
4630 pparams = &adev->use_case_table[audio_usecase];
4631 pcm_params_free(*pparams); /* can accept null input */
4632 *pparams = NULL;
4633
4634 /* find the device ID for the use case (signed, for error) */
4635 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4636 if (device_id < 0)
4637 continue;
4638
4639 /* prepare structures for device probing */
4640 memset(&uc_info, 0, sizeof(uc_info));
4641 uc_info.id = audio_usecase;
4642 uc_info.type = usecase_type;
4643 if (dir) {
4644 adev->active_input = &in;
4645 memset(&in, 0, sizeof(in));
4646 in.device = audio_device;
4647 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4648 uc_info.stream.in = &in;
4649 } else {
4650 adev->active_input = NULL;
4651 }
4652 memset(&out, 0, sizeof(out));
4653 out.devices = audio_device; /* only field needed in select_devices */
4654 uc_info.stream.out = &out;
4655 uc_info.devices = audio_device;
4656 uc_info.in_snd_device = SND_DEVICE_NONE;
4657 uc_info.out_snd_device = SND_DEVICE_NONE;
4658 list_add_tail(&adev->usecase_list, &uc_info.list);
4659
4660 /* select device - similar to start_(in/out)put_stream() */
4661 retval = select_devices(adev, audio_usecase);
4662 if (retval >= 0) {
4663 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4664#if LOG_NDEBUG == 0
4665 if (*pparams) {
4666 ALOGV("%s: (%s) card %d device %d", __func__,
4667 dir ? "input" : "output", card_id, device_id);
4668 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004669 } else {
4670 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4671 }
4672#endif
4673 }
4674
4675 /* deselect device - similar to stop_(in/out)put_stream() */
4676 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004677 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004678 /* 2. Disable the rx device */
4679 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004680 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004681 list_remove(&uc_info.list);
4682 }
4683 }
4684 adev->active_input = NULL; /* restore adev state */
4685 return 0;
4686}
4687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004688static int adev_close(hw_device_t *device)
4689{
Andy Hung31aca912014-03-20 17:14:59 -07004690 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004692
4693 if (!adev)
4694 return 0;
4695
4696 pthread_mutex_lock(&adev_init_lock);
4697
4698 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004699 audio_extn_snd_mon_unregister_listener(adev);
4700 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004701 audio_route_free(adev->audio_route);
4702 free(adev->snd_dev_ref_cnt);
4703 platform_deinit(adev->platform);
4704 audio_extn_extspk_deinit(adev->extspk);
4705 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004706 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004707 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4708 pcm_params_free(adev->use_case_table[i]);
4709 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004710 if (adev->adm_deinit)
4711 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004712 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004713 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004714 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004715
4716 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004718 return 0;
4719}
4720
Glenn Kasten4f993392014-05-14 07:30:48 -07004721/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4722 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4723 * just that it _might_ work.
4724 */
4725static int period_size_is_plausible_for_low_latency(int period_size)
4726{
4727 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004728 case 48:
4729 case 96:
4730 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004731 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004732 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004733 case 240:
4734 case 320:
4735 case 480:
4736 return 1;
4737 default:
4738 return 0;
4739 }
4740}
4741
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004742static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4743{
4744 int card;
4745 card_status_t status;
4746
4747 if (!parms)
4748 return;
4749
4750 if (parse_snd_card_status(parms, &card, &status) < 0)
4751 return;
4752
4753 pthread_mutex_lock(&adev->lock);
4754 bool valid_cb = (card == adev->snd_card);
4755 if (valid_cb) {
4756 if (adev->card_status != status) {
4757 adev->card_status = status;
4758 platform_snd_card_update(adev->platform, status);
4759 }
4760 }
4761 pthread_mutex_unlock(&adev->lock);
4762 return;
4763}
4764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765static int adev_open(const hw_module_t *module, const char *name,
4766 hw_device_t **device)
4767{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004768 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769
Eric Laurent2bafff12016-03-17 12:17:23 -07004770 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004772 pthread_mutex_lock(&adev_init_lock);
4773 if (audio_device_ref_count != 0) {
4774 *device = &adev->device.common;
4775 audio_device_ref_count++;
4776 ALOGV("%s: returning existing instance of adev", __func__);
4777 ALOGV("%s: exit", __func__);
4778 pthread_mutex_unlock(&adev_init_lock);
4779 return 0;
4780 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781 adev = calloc(1, sizeof(struct audio_device));
4782
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004783 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4784
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004785 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4786 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4787 adev->device.common.module = (struct hw_module_t *)module;
4788 adev->device.common.close = adev_close;
4789
4790 adev->device.init_check = adev_init_check;
4791 adev->device.set_voice_volume = adev_set_voice_volume;
4792 adev->device.set_master_volume = adev_set_master_volume;
4793 adev->device.get_master_volume = adev_get_master_volume;
4794 adev->device.set_master_mute = adev_set_master_mute;
4795 adev->device.get_master_mute = adev_get_master_mute;
4796 adev->device.set_mode = adev_set_mode;
4797 adev->device.set_mic_mute = adev_set_mic_mute;
4798 adev->device.get_mic_mute = adev_get_mic_mute;
4799 adev->device.set_parameters = adev_set_parameters;
4800 adev->device.get_parameters = adev_get_parameters;
4801 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4802 adev->device.open_output_stream = adev_open_output_stream;
4803 adev->device.close_output_stream = adev_close_output_stream;
4804 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004805
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004806 adev->device.close_input_stream = adev_close_input_stream;
4807 adev->device.dump = adev_dump;
4808
4809 /* Set the default route before the PCM stream is opened */
4810 pthread_mutex_lock(&adev->lock);
4811 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004812 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004813 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004814 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004815 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004816 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004817 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004818 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004819 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004820 pthread_mutex_unlock(&adev->lock);
4821
4822 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004823 adev->platform = platform_init(adev);
4824 if (!adev->platform) {
4825 free(adev->snd_dev_ref_cnt);
4826 free(adev);
4827 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4828 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004829 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004830 return -EINVAL;
4831 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004832 adev->extspk = audio_extn_extspk_init(adev);
4833
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004834 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4835 if (adev->visualizer_lib == NULL) {
4836 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4837 } else {
4838 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4839 adev->visualizer_start_output =
4840 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4841 "visualizer_hal_start_output");
4842 adev->visualizer_stop_output =
4843 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4844 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004845 }
4846
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004847 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4848 if (adev->offload_effects_lib == NULL) {
4849 ALOGW("%s: DLOPEN failed for %s", __func__,
4850 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4851 } else {
4852 ALOGV("%s: DLOPEN successful for %s", __func__,
4853 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4854 adev->offload_effects_start_output =
4855 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4856 "offload_effects_bundle_hal_start_output");
4857 adev->offload_effects_stop_output =
4858 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4859 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004860 }
4861
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004862 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4863 if (adev->adm_lib == NULL) {
4864 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4865 } else {
4866 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4867 adev->adm_init = (adm_init_t)
4868 dlsym(adev->adm_lib, "adm_init");
4869 adev->adm_deinit = (adm_deinit_t)
4870 dlsym(adev->adm_lib, "adm_deinit");
4871 adev->adm_register_input_stream = (adm_register_input_stream_t)
4872 dlsym(adev->adm_lib, "adm_register_input_stream");
4873 adev->adm_register_output_stream = (adm_register_output_stream_t)
4874 dlsym(adev->adm_lib, "adm_register_output_stream");
4875 adev->adm_deregister_stream = (adm_deregister_stream_t)
4876 dlsym(adev->adm_lib, "adm_deregister_stream");
4877 adev->adm_request_focus = (adm_request_focus_t)
4878 dlsym(adev->adm_lib, "adm_request_focus");
4879 adev->adm_abandon_focus = (adm_abandon_focus_t)
4880 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004881 adev->adm_set_config = (adm_set_config_t)
4882 dlsym(adev->adm_lib, "adm_set_config");
4883 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4884 dlsym(adev->adm_lib, "adm_request_focus_v2");
4885 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4886 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4887 adev->adm_on_routing_change = (adm_on_routing_change_t)
4888 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004889 }
4890
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004891 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004892 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004894 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004895
Andy Hung31aca912014-03-20 17:14:59 -07004896 if (k_enable_extended_precision)
4897 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004898
Glenn Kasten4f993392014-05-14 07:30:48 -07004899 char value[PROPERTY_VALUE_MAX];
4900 int trial;
4901 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4902 trial = atoi(value);
4903 if (period_size_is_plausible_for_low_latency(trial)) {
4904 pcm_config_low_latency.period_size = trial;
4905 pcm_config_low_latency.start_threshold = trial / 4;
4906 pcm_config_low_latency.avail_min = trial / 4;
4907 configured_low_latency_capture_period_size = trial;
4908 }
4909 }
4910 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4911 trial = atoi(value);
4912 if (period_size_is_plausible_for_low_latency(trial)) {
4913 configured_low_latency_capture_period_size = trial;
4914 }
4915 }
4916
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004917 // commented as full set of app type cfg is sent from platform
4918 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004919 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004920
4921 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4922 af_period_multiplier = atoi(value);
4923 if (af_period_multiplier < 0) {
4924 af_period_multiplier = 2;
4925 } else if (af_period_multiplier > 4) {
4926 af_period_multiplier = 4;
4927 }
4928 ALOGV("new period_multiplier = %d", af_period_multiplier);
4929 }
4930
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004931 audio_extn_tfa_98xx_init(adev);
4932
vivek mehta1a9b7c02015-06-25 11:49:38 -07004933 pthread_mutex_unlock(&adev_init_lock);
4934
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004935 if (adev->adm_init)
4936 adev->adm_data = adev->adm_init();
4937
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004938 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004939 audio_extn_snd_mon_init();
4940 pthread_mutex_lock(&adev->lock);
4941 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4942 adev->card_status = CARD_STATUS_ONLINE;
4943 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004944 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004945
Eric Laurent2bafff12016-03-17 12:17:23 -07004946 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004947 return 0;
4948}
4949
4950static struct hw_module_methods_t hal_module_methods = {
4951 .open = adev_open,
4952};
4953
4954struct audio_module HAL_MODULE_INFO_SYM = {
4955 .common = {
4956 .tag = HARDWARE_MODULE_TAG,
4957 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4958 .hal_api_version = HARDWARE_HAL_API_VERSION,
4959 .id = AUDIO_HARDWARE_MODULE_ID,
4960 .name = "QCOM Audio HAL",
4961 .author = "Code Aurora Forum",
4962 .methods = &hal_module_methods,
4963 },
4964};