blob: 685169fe5032653a3f36f4d3e77c82f24152a9eb [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
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700999static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1000 uint32_t *supported_sample_rates __unused,
1001 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001002{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001003 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1004 supported_sample_rates,
1005 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001006#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001007 for (ssize_t i=0; i<count; i++) {
1008 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1009 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010 }
1011#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001012 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001013}
1014
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015static int read_usb_sup_channel_masks(bool is_playback,
1016 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001017 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001018{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001019 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001020 int channel_count;
1021 uint32_t num_masks = 0;
1022 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1023 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001024 }
Eric Laurent74b55762017-07-09 17:04:53 -07001025 if (is_playback) {
1026 // For playback we never report mono because the framework always outputs stereo
1027 channel_count = DEFAULT_CHANNEL_COUNT;
1028 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1029 // above 2 but we want indexed masks here. So we
1030 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1031 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1032 }
1033 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1034 supported_channel_masks[num_masks++] =
1035 audio_channel_mask_for_index_assignment_from_count(channel_count);
1036 }
1037 } else {
1038 // For capture we report all supported channel masks from 1 channel up.
1039 channel_count = MIN_CHANNEL_COUNT;
1040 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1041 // indexed mask
1042 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1043 supported_channel_masks[num_masks++] =
1044 audio_channel_in_mask_from_count(channel_count);
1045 }
1046 }
1047 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1048 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1049 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001050}
1051
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001052static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001053 audio_format_t *supported_formats,
1054 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001055{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001056 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001057 switch (bitwidth) {
1058 case 24:
1059 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001060 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001061 break;
1062 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001063 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001064 break;
1065 case 16:
1066 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001067 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001068 break;
1069 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 ALOGV("%s: %s supported format %d", __func__,
1071 is_playback ? "P" : "C", bitwidth);
1072 return 1;
1073}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001074
Haynes Mathew George569b7482017-05-08 14:44:27 -07001075static int read_usb_sup_params_and_compare(bool is_playback,
1076 audio_format_t *format,
1077 audio_format_t *supported_formats,
1078 uint32_t max_formats,
1079 audio_channel_mask_t *mask,
1080 audio_channel_mask_t *supported_channel_masks,
1081 uint32_t max_masks,
1082 uint32_t *rate,
1083 uint32_t *supported_sample_rates,
1084 uint32_t max_rates) {
1085 int ret = 0;
1086 int num_formats;
1087 int num_masks;
1088 int num_rates;
1089 int i;
1090
1091 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1092 max_formats);
1093 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1094 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001095
Haynes Mathew George569b7482017-05-08 14:44:27 -07001096 num_rates = read_usb_sup_sample_rates(is_playback,
1097 supported_sample_rates, max_rates);
1098
1099#define LUT(table, len, what, dflt) \
1100 for (i=0; i<len && (table[i] != what); i++); \
1101 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1102
1103 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1104 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1105 LUT(supported_sample_rates, num_rates, *rate, 0);
1106
1107#undef LUT
1108 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001109}
1110
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;
Eric Laurentf4520b02017-09-20 18:31:58 -07001167 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1168 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001169
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 usecase = get_usecase_from_list(adev, uc_id);
1171 if (usecase == NULL) {
1172 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1173 return -EINVAL;
1174 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001176 if ((usecase->type == VOICE_CALL) ||
1177 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001178 out_snd_device = platform_get_output_snd_device(adev->platform,
1179 usecase->stream.out->devices);
1180 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 usecase->devices = usecase->stream.out->devices;
1182 } else {
1183 /*
1184 * If the voice call is active, use the sound devices of voice call usecase
1185 * so that it would not result any device switch. All the usecases will
1186 * be switched to new device when select_devices() is called for voice call
1187 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001188 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001189 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001190 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001191 vc_usecase = get_usecase_from_list(adev,
1192 get_voice_usecase_id_from_list(adev));
1193 if ((vc_usecase != NULL) &&
1194 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1195 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001196 in_snd_device = vc_usecase->in_snd_device;
1197 out_snd_device = vc_usecase->out_snd_device;
1198 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001199 } else if (audio_extn_hfp_is_active(adev)) {
1200 hfp_ucid = audio_extn_hfp_get_usecase();
1201 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1202 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1203 in_snd_device = hfp_usecase->in_snd_device;
1204 out_snd_device = hfp_usecase->out_snd_device;
1205 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001206 }
1207 if (usecase->type == PCM_PLAYBACK) {
1208 usecase->devices = usecase->stream.out->devices;
1209 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001210 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001211 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001212
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
Eric Laurentf4520b02017-09-20 18:31:58 -07001363 if (usecase == voip_usecase) {
1364 struct stream_out *voip_out = voip_usecase->stream.out;
1365 audio_extn_utils_send_app_type_gain(adev,
1366 voip_out->app_type_cfg.app_type,
1367 &voip_out->app_type_cfg.gain[0]);
1368 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001369 return status;
1370}
1371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372static int stop_input_stream(struct stream_in *in)
1373{
1374 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375 struct audio_usecase *uc_info;
1376 struct audio_device *adev = in->dev;
1377
Eric Laurent994a6932013-07-17 11:51:42 -07001378 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001379 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001380
1381 if (adev->active_input) {
1382 if (adev->active_input->usecase == in->usecase) {
1383 adev->active_input = NULL;
1384 } else {
1385 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1386 __func__,
1387 use_case_table[adev->active_input->usecase],
1388 use_case_table[in->usecase]);
1389 }
1390 }
1391
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001392 uc_info = get_usecase_from_list(adev, in->usecase);
1393 if (uc_info == NULL) {
1394 ALOGE("%s: Could not find the usecase (%d) in the list",
1395 __func__, in->usecase);
1396 return -EINVAL;
1397 }
1398
vivek mehta781065c2017-04-04 12:55:01 -07001399 /* Close in-call recording streams */
1400 voice_check_and_stop_incall_rec_usecase(adev, in);
1401
Eric Laurent150dbfe2013-02-27 14:31:02 -08001402 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001403 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001404
1405 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001406 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001408 list_remove(&uc_info->list);
1409 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001410
Eric Laurent994a6932013-07-17 11:51:42 -07001411 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001412 return ret;
1413}
1414
1415int start_input_stream(struct stream_in *in)
1416{
1417 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001418 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001419 struct audio_usecase *uc_info;
1420 struct audio_device *adev = in->dev;
1421
Eric Laurent994a6932013-07-17 11:51:42 -07001422 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001423
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001424 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1425 return -EIO;
1426
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001427 if (in->card_status == CARD_STATUS_OFFLINE ||
1428 adev->card_status == CARD_STATUS_OFFLINE) {
1429 ALOGW("in->card_status or adev->card_status offline, try again");
1430 ret = -EAGAIN;
1431 goto error_config;
1432 }
1433
vivek mehta781065c2017-04-04 12:55:01 -07001434 /* Check if source matches incall recording usecase criteria */
1435 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1436 if (ret)
1437 goto error_config;
1438 else
1439 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1440
Eric Laurentb23d5282013-05-14 15:27:20 -07001441 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442 if (in->pcm_device_id < 0) {
1443 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1444 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001445 ret = -EINVAL;
1446 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001448
1449 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1451 uc_info->id = in->usecase;
1452 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001453 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001454 uc_info->devices = in->device;
1455 uc_info->in_snd_device = SND_DEVICE_NONE;
1456 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001458 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001459
1460 audio_extn_perf_lock_acquire();
1461
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463
Eric Laurent0e46adf2016-12-16 12:49:24 -08001464 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001465 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001466 ALOGE("%s: pcm stream not ready", __func__);
1467 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001468 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001469 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001470 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001471 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1472 goto error_open;
1473 }
1474 } else {
1475 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1476 unsigned int pcm_open_retry_count = 0;
1477
1478 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1479 flags |= PCM_MMAP | PCM_NOIRQ;
1480 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1481 } else if (in->realtime) {
1482 flags |= PCM_MMAP | PCM_NOIRQ;
1483 }
1484
1485 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1486 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1487
1488 while (1) {
1489 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1490 flags, &in->config);
1491 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1492 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1493 if (in->pcm != NULL) {
1494 pcm_close(in->pcm);
1495 in->pcm = NULL;
1496 }
1497 if (pcm_open_retry_count-- == 0) {
1498 ret = -EIO;
1499 goto error_open;
1500 }
1501 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1502 continue;
1503 }
1504 break;
1505 }
1506
1507 ALOGV("%s: pcm_prepare", __func__);
1508 ret = pcm_prepare(in->pcm);
1509 if (ret < 0) {
1510 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001511 pcm_close(in->pcm);
1512 in->pcm = NULL;
1513 goto error_open;
1514 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001515 if (in->realtime) {
1516 ret = pcm_start(in->pcm);
1517 if (ret < 0) {
1518 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1519 pcm_close(in->pcm);
1520 in->pcm = NULL;
1521 goto error_open;
1522 }
1523 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001524 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001525 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001526 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001527 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001528
Eric Laurent0e46adf2016-12-16 12:49:24 -08001529 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001530
1531error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001533 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001534
1535error_config:
1536 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001537 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001538 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539}
1540
Eric Laurenta1478072015-09-21 17:21:52 -07001541void lock_input_stream(struct stream_in *in)
1542{
1543 pthread_mutex_lock(&in->pre_lock);
1544 pthread_mutex_lock(&in->lock);
1545 pthread_mutex_unlock(&in->pre_lock);
1546}
1547
1548void lock_output_stream(struct stream_out *out)
1549{
1550 pthread_mutex_lock(&out->pre_lock);
1551 pthread_mutex_lock(&out->lock);
1552 pthread_mutex_unlock(&out->pre_lock);
1553}
1554
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001555/* must be called with out->lock locked */
1556static int send_offload_cmd_l(struct stream_out* out, int command)
1557{
1558 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1559
1560 ALOGVV("%s %d", __func__, command);
1561
1562 cmd->cmd = command;
1563 list_add_tail(&out->offload_cmd_list, &cmd->node);
1564 pthread_cond_signal(&out->offload_cond);
1565 return 0;
1566}
1567
1568/* must be called iwth out->lock locked */
1569static void stop_compressed_output_l(struct stream_out *out)
1570{
1571 out->offload_state = OFFLOAD_STATE_IDLE;
1572 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001573 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001574 if (out->compr != NULL) {
1575 compress_stop(out->compr);
1576 while (out->offload_thread_blocked) {
1577 pthread_cond_wait(&out->cond, &out->lock);
1578 }
1579 }
1580}
1581
1582static void *offload_thread_loop(void *context)
1583{
1584 struct stream_out *out = (struct stream_out *) context;
1585 struct listnode *item;
1586
1587 out->offload_state = OFFLOAD_STATE_IDLE;
1588 out->playback_started = 0;
1589
1590 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1591 set_sched_policy(0, SP_FOREGROUND);
1592 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1593
1594 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001595 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001596 for (;;) {
1597 struct offload_cmd *cmd = NULL;
1598 stream_callback_event_t event;
1599 bool send_callback = false;
1600
1601 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1602 __func__, list_empty(&out->offload_cmd_list),
1603 out->offload_state);
1604 if (list_empty(&out->offload_cmd_list)) {
1605 ALOGV("%s SLEEPING", __func__);
1606 pthread_cond_wait(&out->offload_cond, &out->lock);
1607 ALOGV("%s RUNNING", __func__);
1608 continue;
1609 }
1610
1611 item = list_head(&out->offload_cmd_list);
1612 cmd = node_to_item(item, struct offload_cmd, node);
1613 list_remove(item);
1614
1615 ALOGVV("%s STATE %d CMD %d out->compr %p",
1616 __func__, out->offload_state, cmd->cmd, out->compr);
1617
1618 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1619 free(cmd);
1620 break;
1621 }
1622
1623 if (out->compr == NULL) {
1624 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001625 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001626 pthread_cond_signal(&out->cond);
1627 continue;
1628 }
1629 out->offload_thread_blocked = true;
1630 pthread_mutex_unlock(&out->lock);
1631 send_callback = false;
1632 switch(cmd->cmd) {
1633 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1634 compress_wait(out->compr, -1);
1635 send_callback = true;
1636 event = STREAM_CBK_EVENT_WRITE_READY;
1637 break;
1638 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001639 compress_next_track(out->compr);
1640 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001641 send_callback = true;
1642 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001643 /* Resend the metadata for next iteration */
1644 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001645 break;
1646 case OFFLOAD_CMD_DRAIN:
1647 compress_drain(out->compr);
1648 send_callback = true;
1649 event = STREAM_CBK_EVENT_DRAIN_READY;
1650 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001651 case OFFLOAD_CMD_ERROR:
1652 send_callback = true;
1653 event = STREAM_CBK_EVENT_ERROR;
1654 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001655 default:
1656 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1657 break;
1658 }
Eric Laurenta1478072015-09-21 17:21:52 -07001659 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001660 out->offload_thread_blocked = false;
1661 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001662 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001663 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001664 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001665 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001666 free(cmd);
1667 }
1668
1669 pthread_cond_signal(&out->cond);
1670 while (!list_empty(&out->offload_cmd_list)) {
1671 item = list_head(&out->offload_cmd_list);
1672 list_remove(item);
1673 free(node_to_item(item, struct offload_cmd, node));
1674 }
1675 pthread_mutex_unlock(&out->lock);
1676
1677 return NULL;
1678}
1679
1680static int create_offload_callback_thread(struct stream_out *out)
1681{
1682 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1683 list_init(&out->offload_cmd_list);
1684 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1685 offload_thread_loop, out);
1686 return 0;
1687}
1688
1689static int destroy_offload_callback_thread(struct stream_out *out)
1690{
Eric Laurenta1478072015-09-21 17:21:52 -07001691 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001692 stop_compressed_output_l(out);
1693 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1694
1695 pthread_mutex_unlock(&out->lock);
1696 pthread_join(out->offload_thread, (void **) NULL);
1697 pthread_cond_destroy(&out->offload_cond);
1698
1699 return 0;
1700}
1701
Eric Laurent07eeafd2013-10-06 12:52:49 -07001702static bool allow_hdmi_channel_config(struct audio_device *adev)
1703{
1704 struct listnode *node;
1705 struct audio_usecase *usecase;
1706 bool ret = true;
1707
1708 list_for_each(node, &adev->usecase_list) {
1709 usecase = node_to_item(node, struct audio_usecase, list);
1710 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1711 /*
1712 * If voice call is already existing, do not proceed further to avoid
1713 * disabling/enabling both RX and TX devices, CSD calls, etc.
1714 * Once the voice call done, the HDMI channels can be configured to
1715 * max channels of remaining use cases.
1716 */
1717 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001718 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001719 __func__);
1720 ret = false;
1721 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001722 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1723 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001724 "no change in HDMI channels", __func__);
1725 ret = false;
1726 break;
1727 }
1728 }
1729 }
1730 return ret;
1731}
1732
1733static int check_and_set_hdmi_channels(struct audio_device *adev,
1734 unsigned int channels)
1735{
1736 struct listnode *node;
1737 struct audio_usecase *usecase;
1738
1739 /* Check if change in HDMI channel config is allowed */
1740 if (!allow_hdmi_channel_config(adev))
1741 return 0;
1742
1743 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001744 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001745 return 0;
1746 }
1747
1748 platform_set_hdmi_channels(adev->platform, channels);
1749 adev->cur_hdmi_channels = channels;
1750
1751 /*
1752 * Deroute all the playback streams routed to HDMI so that
1753 * the back end is deactivated. Note that backend will not
1754 * be deactivated if any one stream is connected to it.
1755 */
1756 list_for_each(node, &adev->usecase_list) {
1757 usecase = node_to_item(node, struct audio_usecase, list);
1758 if (usecase->type == PCM_PLAYBACK &&
1759 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001760 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001761 }
1762 }
1763
1764 /*
1765 * Enable all the streams disabled above. Now the HDMI backend
1766 * will be activated with new channel configuration
1767 */
1768 list_for_each(node, &adev->usecase_list) {
1769 usecase = node_to_item(node, struct audio_usecase, list);
1770 if (usecase->type == PCM_PLAYBACK &&
1771 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001772 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001773 }
1774 }
1775
1776 return 0;
1777}
1778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779static int stop_output_stream(struct stream_out *out)
1780{
1781 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782 struct audio_usecase *uc_info;
1783 struct audio_device *adev = out->dev;
1784
Eric Laurent994a6932013-07-17 11:51:42 -07001785 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001786 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787 uc_info = get_usecase_from_list(adev, out->usecase);
1788 if (uc_info == NULL) {
1789 ALOGE("%s: Could not find the usecase (%d) in the list",
1790 __func__, out->usecase);
1791 return -EINVAL;
1792 }
1793
Haynes Mathew George41f86652014-06-17 14:22:15 -07001794 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1795 if (adev->visualizer_stop_output != NULL)
1796 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1797 if (adev->offload_effects_stop_output != NULL)
1798 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1799 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001800
Eric Laurent150dbfe2013-02-27 14:31:02 -08001801 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001802 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001803
1804 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001805 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001807 list_remove(&uc_info->list);
1808 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809
Eric Laurent0499d4f2014-08-25 22:39:29 -05001810 audio_extn_extspk_update(adev->extspk);
1811
Eric Laurent07eeafd2013-10-06 12:52:49 -07001812 /* Must be called after removing the usecase from list */
1813 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1814 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001815 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1816 struct listnode *node;
1817 struct audio_usecase *usecase;
1818 list_for_each(node, &adev->usecase_list) {
1819 usecase = node_to_item(node, struct audio_usecase, list);
1820 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1821 select_devices(adev, usecase->id);
1822 }
1823 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001824
Eric Laurent994a6932013-07-17 11:51:42 -07001825 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001826 return ret;
1827}
1828
1829int start_output_stream(struct stream_out *out)
1830{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832 struct audio_usecase *uc_info;
1833 struct audio_device *adev = out->dev;
1834
Eric Laurent994a6932013-07-17 11:51:42 -07001835 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001836 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001837
1838 if (out->card_status == CARD_STATUS_OFFLINE ||
1839 adev->card_status == CARD_STATUS_OFFLINE) {
1840 ALOGW("out->card_status or adev->card_status offline, try again");
1841 ret = -EAGAIN;
1842 goto error_config;
1843 }
1844
Eric Laurentb23d5282013-05-14 15:27:20 -07001845 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 if (out->pcm_device_id < 0) {
1847 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1848 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001849 ret = -EINVAL;
1850 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 }
1852
1853 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1854 uc_info->id = out->usecase;
1855 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001856 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001857 uc_info->devices = out->devices;
1858 uc_info->in_snd_device = SND_DEVICE_NONE;
1859 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860
Eric Laurent07eeafd2013-10-06 12:52:49 -07001861 /* This must be called before adding this usecase to the list */
1862 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1863 check_and_set_hdmi_channels(adev, out->config.channels);
1864
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001865 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001867 audio_extn_perf_lock_acquire();
1868
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001869 select_devices(adev, out->usecase);
1870
Eric Laurent0499d4f2014-08-25 22:39:29 -05001871 audio_extn_extspk_update(adev->extspk);
1872
Andy Hung31aca912014-03-20 17:14:59 -07001873 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001874 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001875 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1876 out->pcm = NULL;
1877 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1878 COMPRESS_IN, &out->compr_config);
1879 if (out->compr && !is_compress_ready(out->compr)) {
1880 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1881 compress_close(out->compr);
1882 out->compr = NULL;
1883 ret = -EIO;
1884 goto error_open;
1885 }
1886 if (out->offload_callback)
1887 compress_nonblock(out->compr, out->non_blocking);
1888
1889 if (adev->visualizer_start_output != NULL)
1890 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1891 if (adev->offload_effects_start_output != NULL)
1892 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1893 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001894 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001895 ALOGE("%s: pcm stream not ready", __func__);
1896 goto error_open;
1897 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001898 ret = pcm_start(out->pcm);
1899 if (ret < 0) {
1900 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1901 goto error_open;
1902 }
1903 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001904 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001905 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001906
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001907 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1908 flags |= PCM_MMAP | PCM_NOIRQ;
1909 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001910 } else if (out->realtime) {
1911 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001912 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001913
1914 while (1) {
1915 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1916 flags, &out->config);
1917 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1918 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1919 if (out->pcm != NULL) {
1920 pcm_close(out->pcm);
1921 out->pcm = NULL;
1922 }
1923 if (pcm_open_retry_count-- == 0) {
1924 ret = -EIO;
1925 goto error_open;
1926 }
1927 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1928 continue;
1929 }
1930 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001931 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001932 ALOGV("%s: pcm_prepare", __func__);
1933 if (pcm_is_ready(out->pcm)) {
1934 ret = pcm_prepare(out->pcm);
1935 if (ret < 0) {
1936 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1937 pcm_close(out->pcm);
1938 out->pcm = NULL;
1939 goto error_open;
1940 }
1941 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001942 if (out->realtime) {
1943 ret = pcm_start(out->pcm);
1944 if (ret < 0) {
1945 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1946 pcm_close(out->pcm);
1947 out->pcm = NULL;
1948 goto error_open;
1949 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001950 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001951 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001952 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001953 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001954 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07001955
1956 // consider a scenario where on pause lower layers are tear down.
1957 // so on resume, swap mixer control need to be sent only when
1958 // backend is active, hence rather than sending from enable device
1959 // sending it from start of streamtream
1960
1961 platform_set_swap_channels(adev, true);
1962
Eric Laurent994a6932013-07-17 11:51:42 -07001963 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001964 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001965error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001966 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001968error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001969 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970}
1971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972static int check_input_parameters(uint32_t sample_rate,
1973 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001974 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001976 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1977 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001978 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1979 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001980 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1981 return -EINVAL;
1982 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983
Eric Laurent74b55762017-07-09 17:04:53 -07001984 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1985 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001986 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001987 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001988 return -EINVAL;
1989 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990
1991 switch (sample_rate) {
1992 case 8000:
1993 case 11025:
1994 case 12000:
1995 case 16000:
1996 case 22050:
1997 case 24000:
1998 case 32000:
1999 case 44100:
2000 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002001 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002 break;
2003 default:
vivek mehtadae44712015-07-27 14:13:18 -07002004 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005 return -EINVAL;
2006 }
2007
2008 return 0;
2009}
2010
vivek mehtaa68fea62017-06-08 19:04:02 -07002011static size_t get_stream_buffer_size(size_t duration_ms,
2012 uint32_t sample_rate,
2013 audio_format_t format,
2014 int channel_count,
2015 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016{
2017 size_t size = 0;
2018
vivek mehtaa68fea62017-06-08 19:04:02 -07002019 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002020 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002021 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002022
2023 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024
Glenn Kasten4f993392014-05-14 07:30:48 -07002025 /* make sure the size is multiple of 32 bytes
2026 * At 48 kHz mono 16-bit PCM:
2027 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2028 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2029 */
2030 size += 0x1f;
2031 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002032
2033 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034}
2035
2036static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2037{
2038 struct stream_out *out = (struct stream_out *)stream;
2039
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002040 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041}
2042
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002043static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044{
2045 return -ENOSYS;
2046}
2047
2048static size_t out_get_buffer_size(const struct audio_stream *stream)
2049{
2050 struct stream_out *out = (struct stream_out *)stream;
2051
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2053 return out->compr_config.fragment_size;
2054 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002055 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002056 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057}
2058
2059static uint32_t out_get_channels(const struct audio_stream *stream)
2060{
2061 struct stream_out *out = (struct stream_out *)stream;
2062
2063 return out->channel_mask;
2064}
2065
2066static audio_format_t out_get_format(const struct audio_stream *stream)
2067{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068 struct stream_out *out = (struct stream_out *)stream;
2069
2070 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071}
2072
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002073static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074{
2075 return -ENOSYS;
2076}
2077
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002078/* must be called with out->lock locked */
2079static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080{
2081 struct stream_out *out = (struct stream_out *)stream;
2082 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002083 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002085 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002086 if (adev->adm_deregister_stream)
2087 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002088 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002089 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002090 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2091 if (out->pcm) {
2092 pcm_close(out->pcm);
2093 out->pcm = NULL;
2094 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002095 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002096 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002097 out->playback_started = false;
2098 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099 } else {
2100 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002101 out->gapless_mdata.encoder_delay = 0;
2102 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002103 if (out->compr != NULL) {
2104 compress_close(out->compr);
2105 out->compr = NULL;
2106 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002107 }
Phil Burkbc991042017-02-24 08:06:44 -08002108 if (do_stop) {
2109 stop_output_stream(out);
2110 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002111 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002113 return 0;
2114}
2115
2116static int out_standby(struct audio_stream *stream)
2117{
2118 struct stream_out *out = (struct stream_out *)stream;
2119
2120 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2121 out->usecase, use_case_table[out->usecase]);
2122
2123 lock_output_stream(out);
2124 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002126 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127 return 0;
2128}
2129
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002130static int out_on_error(struct audio_stream *stream)
2131{
2132 struct stream_out *out = (struct stream_out *)stream;
2133 struct audio_device *adev = out->dev;
2134 bool do_standby = false;
2135
2136 lock_output_stream(out);
2137 if (!out->standby) {
2138 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2139 stop_compressed_output_l(out);
2140 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2141 } else
2142 do_standby = true;
2143 }
2144 pthread_mutex_unlock(&out->lock);
2145
2146 if (do_standby)
2147 return out_standby(&out->stream.common);
2148
2149 return 0;
2150}
2151
Andy Hung7401c7c2016-09-21 12:41:21 -07002152static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153{
Andy Hung7401c7c2016-09-21 12:41:21 -07002154 struct stream_out *out = (struct stream_out *)stream;
2155
2156 // We try to get the lock for consistency,
2157 // but it isn't necessary for these variables.
2158 // If we're not in standby, we may be blocked on a write.
2159 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2160 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2161 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2162
2163 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002164 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002165 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002166
2167 // dump error info
2168 (void)error_log_dump(
2169 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171 return 0;
2172}
2173
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002174static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2175{
2176 int ret = 0;
2177 char value[32];
2178 struct compr_gapless_mdata tmp_mdata;
2179
2180 if (!out || !parms) {
2181 return -EINVAL;
2182 }
2183
2184 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2185 if (ret >= 0) {
2186 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2187 } else {
2188 return -EINVAL;
2189 }
2190
2191 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2192 if (ret >= 0) {
2193 tmp_mdata.encoder_padding = atoi(value);
2194 } else {
2195 return -EINVAL;
2196 }
2197
2198 out->gapless_mdata = tmp_mdata;
2199 out->send_new_metadata = 1;
2200 ALOGV("%s new encoder delay %u and padding %u", __func__,
2201 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2202
2203 return 0;
2204}
2205
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002206static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2207{
2208 return out == adev->primary_output || out == adev->voice_tx_output;
2209}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002210
Kevin Rocard1e02c882017-08-09 15:26:07 -07002211static int get_alive_usb_card(struct str_parms* parms) {
2212 int card;
2213 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2214 !audio_extn_usb_alive(card)) {
2215 return card;
2216 }
2217 return -ENODEV;
2218}
2219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2221{
2222 struct stream_out *out = (struct stream_out *)stream;
2223 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002224 struct audio_usecase *usecase;
2225 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 struct str_parms *parms;
2227 char value[32];
2228 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002229 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002230 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231
Eric Laurent2e140aa2016-06-30 17:14:46 -07002232 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002233 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 parms = str_parms_create_str(kvpairs);
2235 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2236 if (ret >= 0) {
2237 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002238
Eric Laurenta1478072015-09-21 17:21:52 -07002239 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002240
2241 // The usb driver needs to be closed after usb device disconnection
2242 // otherwise audio is no longer played on the new usb devices.
2243 // By forcing the stream in standby, the usb stack refcount drops to 0
2244 // and the driver is closed.
2245 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2246 audio_is_usb_out_device(out->devices)) {
2247 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2248 out_standby_l(&out->stream.common);
2249 }
2250
Eric Laurent150dbfe2013-02-27 14:31:02 -08002251 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002253 /*
2254 * When HDMI cable is unplugged the music playback is paused and
2255 * the policy manager sends routing=0. But the audioflinger
2256 * continues to write data until standby time (3sec).
2257 * As the HDMI core is turned off, the write gets blocked.
2258 * Avoid this by routing audio to speaker until standby.
2259 */
2260 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2261 val == AUDIO_DEVICE_NONE) {
2262 val = AUDIO_DEVICE_OUT_SPEAKER;
2263 }
2264
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002265 audio_devices_t new_dev = val;
2266
2267 // Workaround: If routing to an non existing usb device, fail gracefully
2268 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002269 int card;
2270 if (audio_is_usb_out_device(new_dev) &&
2271 (card = get_alive_usb_card(parms)) >= 0) {
2272
2273 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002274 pthread_mutex_unlock(&adev->lock);
2275 pthread_mutex_unlock(&out->lock);
2276 status = -ENOSYS;
2277 goto routing_fail;
2278 }
2279
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002280 /*
2281 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002282 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002283 * the select_devices(). But how do we undo this?
2284 *
2285 * For example, music playback is active on headset (deep-buffer usecase)
2286 * and if we go to ringtones and select a ringtone, low-latency usecase
2287 * will be started on headset+speaker. As we can't enable headset+speaker
2288 * and headset devices at the same time, select_devices() switches the music
2289 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2290 * So when the ringtone playback is completed, how do we undo the same?
2291 *
2292 * We are relying on the out_set_parameters() call on deep-buffer output,
2293 * once the ringtone playback is ended.
2294 * NOTE: We should not check if the current devices are same as new devices.
2295 * Because select_devices() must be called to switch back the music
2296 * playback to headset.
2297 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002298 if (new_dev != AUDIO_DEVICE_NONE) {
2299 bool same_dev = out->devices == new_dev;
2300 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002301
Eric Laurenta7657192014-10-09 21:09:33 -07002302 if (output_drives_call(adev, out)) {
2303 if (!voice_is_in_call(adev)) {
2304 if (adev->mode == AUDIO_MODE_IN_CALL) {
2305 adev->current_call_output = out;
2306 ret = voice_start_call(adev);
2307 }
2308 } else {
2309 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002310 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002311 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002312 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002313
2314 if (!out->standby) {
2315 if (!same_dev) {
2316 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002317 // inform adm before actual routing to prevent glitches.
2318 if (adev->adm_on_routing_change) {
2319 adev->adm_on_routing_change(adev->adm_data,
2320 out->handle);
2321 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002322 }
2323 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002324 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002325
2326 // on device switch force swap, lower functions will make sure
2327 // to check if swap is allowed or not.
2328
2329 if (!same_dev)
2330 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002331 }
2332
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002333 }
2334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002336 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002337
2338 /*handles device and call state changes*/
2339 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002341 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002342
2343 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2344 parse_compress_metadata(out, parms);
2345 }
2346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002348 ALOGV("%s: exit: code(%d)", __func__, status);
2349 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002350}
2351
Haynes Mathew George569b7482017-05-08 14:44:27 -07002352static bool stream_get_parameter_channels(struct str_parms *query,
2353 struct str_parms *reply,
2354 audio_channel_mask_t *supported_channel_masks) {
2355 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002356 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002358 size_t i, j;
2359
2360 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2361 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362 value[0] = '\0';
2363 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002364 while (supported_channel_masks[i] != 0) {
2365 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2366 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367 if (!first) {
2368 strcat(value, "|");
2369 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002370 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371 first = false;
2372 break;
2373 }
2374 }
2375 i++;
2376 }
2377 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002378 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002379 return ret >= 0;
2380}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002381
Haynes Mathew George569b7482017-05-08 14:44:27 -07002382static bool stream_get_parameter_formats(struct str_parms *query,
2383 struct str_parms *reply,
2384 audio_format_t *supported_formats) {
2385 int ret = -1;
2386 char value[256];
2387 int i;
2388
2389 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2390 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002391 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002392 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002393 case AUDIO_FORMAT_PCM_16_BIT:
2394 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2395 break;
2396 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2397 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2398 break;
2399 case AUDIO_FORMAT_PCM_32_BIT:
2400 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2401 break;
2402 default:
2403 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002404 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002405 break;
2406 }
2407 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002408 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002409 return ret >= 0;
2410}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002411
Haynes Mathew George569b7482017-05-08 14:44:27 -07002412static bool stream_get_parameter_rates(struct str_parms *query,
2413 struct str_parms *reply,
2414 uint32_t *supported_sample_rates) {
2415
2416 int i;
2417 char value[256];
2418 int ret = -1;
2419 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2420 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002421 value[0] = '\0';
2422 i=0;
2423 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002424 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002425 int avail = sizeof(value) - cursor;
2426 ret = snprintf(value + cursor, avail, "%s%d",
2427 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002428 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002429 if (ret < 0 || ret >= avail) {
2430 // if cursor is at the last element of the array
2431 // overwrite with \0 is duplicate work as
2432 // snprintf already put a \0 in place.
2433 // else
2434 // we had space to write the '|' at value[cursor]
2435 // (which will be overwritten) or no space to fill
2436 // the first element (=> cursor == 0)
2437 value[cursor] = '\0';
2438 break;
2439 }
2440 cursor += ret;
2441 ++i;
2442 }
2443 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2444 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002445 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002446 return ret >= 0;
2447}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002448
Haynes Mathew George569b7482017-05-08 14:44:27 -07002449static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2450{
2451 struct stream_out *out = (struct stream_out *)stream;
2452 struct str_parms *query = str_parms_create_str(keys);
2453 char *str;
2454 struct str_parms *reply = str_parms_create();
2455 bool replied = false;
2456 ALOGV("%s: enter: keys - %s", __func__, keys);
2457
2458 replied |= stream_get_parameter_channels(query, reply,
2459 &out->supported_channel_masks[0]);
2460 replied |= stream_get_parameter_formats(query, reply,
2461 &out->supported_formats[0]);
2462 replied |= stream_get_parameter_rates(query, reply,
2463 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002464 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 str = str_parms_to_str(reply);
2466 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002467 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 }
2469 str_parms_destroy(query);
2470 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002471 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472 return str;
2473}
2474
2475static uint32_t out_get_latency(const struct audio_stream_out *stream)
2476{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002477 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002478 struct stream_out *out = (struct stream_out *)stream;
2479
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002480 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2481 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002482 else if ((out->realtime) ||
2483 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002484 // since the buffer won't be filled up faster than realtime,
2485 // return a smaller number
2486 period_ms = (out->af_period_multiplier * out->config.period_size *
2487 1000) / (out->config.rate);
2488 hw_delay = platform_render_latency(out->usecase)/1000;
2489 return period_ms + hw_delay;
2490 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002491
2492 return (out->config.period_count * out->config.period_size * 1000) /
2493 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494}
2495
2496static int out_set_volume(struct audio_stream_out *stream, float left,
2497 float right)
2498{
Eric Laurenta9024de2013-04-04 09:19:12 -07002499 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002500 int volume[2];
2501
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002502 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002503 /* only take left channel into account: the API is for stereo anyway */
2504 out->muted = (left == 0.0f);
2505 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002506 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2507 const char *mixer_ctl_name = "Compress Playback Volume";
2508 struct audio_device *adev = out->dev;
2509 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002510 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2511 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002512 /* try with the control based on device id */
2513 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2514 PCM_PLAYBACK);
2515 char ctl_name[128] = {0};
2516 snprintf(ctl_name, sizeof(ctl_name),
2517 "Compress Playback %d Volume", pcm_device_id);
2518 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2519 if (!ctl) {
2520 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2521 return -EINVAL;
2522 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002523 }
2524 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2525 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2526 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2527 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002528 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002529 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2530 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2531 if (!out->standby) {
2532 // if in standby, cached volume will be sent after stream is opened
2533 audio_extn_utils_send_app_type_gain(out->dev,
2534 out->app_type_cfg.app_type,
2535 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002536 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002537 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002538 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002540 return -ENOSYS;
2541}
2542
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002543// note: this call is safe only if the stream_cb is
2544// removed first in close_output_stream (as is done now).
2545static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2546{
2547 if (!stream || !parms)
2548 return;
2549
2550 struct stream_out *out = (struct stream_out *)stream;
2551 struct audio_device *adev = out->dev;
2552
2553 card_status_t status;
2554 int card;
2555 if (parse_snd_card_status(parms, &card, &status) < 0)
2556 return;
2557
2558 pthread_mutex_lock(&adev->lock);
2559 bool valid_cb = (card == adev->snd_card);
2560 pthread_mutex_unlock(&adev->lock);
2561
2562 if (!valid_cb)
2563 return;
2564
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002565 lock_output_stream(out);
2566 if (out->card_status != status)
2567 out->card_status = status;
2568 pthread_mutex_unlock(&out->lock);
2569
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002570 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2571 use_case_table[out->usecase],
2572 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2573
2574 if (status == CARD_STATUS_OFFLINE)
2575 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002576
2577 return;
2578}
2579
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002580#ifdef NO_AUDIO_OUT
2581static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002582 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002583{
2584 struct stream_out *out = (struct stream_out *)stream;
2585
2586 /* No Output device supported other than BT for playback.
2587 * Sleep for the amount of buffer duration
2588 */
Eric Laurenta1478072015-09-21 17:21:52 -07002589 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002590 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2591 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002592 out_get_sample_rate(&out->stream.common));
2593 pthread_mutex_unlock(&out->lock);
2594 return bytes;
2595}
2596#endif
2597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2599 size_t bytes)
2600{
2601 struct stream_out *out = (struct stream_out *)stream;
2602 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002603 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002604 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002605
Eric Laurenta1478072015-09-21 17:21:52 -07002606 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002607 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002608 const size_t frame_size = audio_stream_out_frame_size(stream);
2609 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002610
Eric Laurent0e46adf2016-12-16 12:49:24 -08002611 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2612 error_code = ERROR_CODE_WRITE;
2613 goto exit;
2614 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002616 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002617 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002619
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002620 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002622 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002623 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 goto exit;
2625 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002626
vivek mehta40125092017-08-21 18:48:51 -07002627 // after standby always force set last known cal step
2628 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2629 ALOGD("%s: retry previous failed cal level set", __func__);
2630 send_gain_dep_calibration_l();
2631 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002634 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002635 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002636 if (out->send_new_metadata) {
2637 ALOGVV("send new gapless metadata");
2638 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2639 out->send_new_metadata = 0;
2640 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002641 unsigned int avail;
2642 struct timespec tstamp;
2643 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2644 /* Do not limit write size if the available frames count is unknown */
2645 if (ret != 0) {
2646 avail = bytes;
2647 }
2648 if (avail == 0) {
2649 ret = 0;
2650 } else {
2651 if (avail > bytes) {
2652 avail = bytes;
2653 }
2654 ret = compress_write(out->compr, buffer, avail);
2655 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2656 __func__, avail, ret);
2657 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002658
Eric Laurent6e895242013-09-05 16:10:57 -07002659 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002660 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2661 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002662 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002663 compress_start(out->compr);
2664 out->playback_started = 1;
2665 out->offload_state = OFFLOAD_STATE_PLAYING;
2666 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002667 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002668 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002669 } else {
2670 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002671 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002672 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002673 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002674 return ret;
2675 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002676 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002677 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002678 size_t bytes_to_write = bytes;
2679
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002680 if (out->muted)
2681 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002682 // FIXME: this can be removed once audio flinger mixer supports mono output
2683 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
2684 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2685 int16_t *src = (int16_t *)buffer;
2686 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002687
Eric Laurentad2dde92017-09-20 18:27:31 -07002688 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2689 out->format != AUDIO_FORMAT_PCM_16_BIT,
2690 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002691
Eric Laurentad2dde92017-09-20 18:27:31 -07002692 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2693 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2694 }
2695 bytes_to_write /= 2;
2696 }
2697 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2698
2699 long ns = (frames * NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002700 request_out_focus(out, ns);
2701
2702 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2703 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002704 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002705 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002706 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002707
Haynes Mathew George03c40102016-01-29 17:57:48 -08002708 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002709 } else {
2710 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002711 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 }
2713
2714exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002715 // For PCM we always consume the buffer and return #bytes regardless of ret.
2716 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002717 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002718 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002719 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002720
Andy Hung7401c7c2016-09-21 12:41:21 -07002721 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002722 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002723 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2724 ALOGE_IF(out->pcm != NULL,
2725 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002726 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002727 // usleep not guaranteed for values over 1 second but we don't limit here.
2728 }
2729 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731 pthread_mutex_unlock(&out->lock);
2732
2733 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002734 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002735 if (sleeptime_us != 0)
2736 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 }
2738 return bytes;
2739}
2740
2741static int out_get_render_position(const struct audio_stream_out *stream,
2742 uint32_t *dsp_frames)
2743{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002744 struct stream_out *out = (struct stream_out *)stream;
2745 *dsp_frames = 0;
2746 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002747 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002748 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002749 unsigned long frames = 0;
2750 // TODO: check return value
2751 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2752 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002753 ALOGVV("%s rendered frames %d sample_rate %d",
2754 __func__, *dsp_frames, out->sample_rate);
2755 }
2756 pthread_mutex_unlock(&out->lock);
2757 return 0;
2758 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002759 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760}
2761
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002762static int out_add_audio_effect(const struct audio_stream *stream __unused,
2763 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764{
2765 return 0;
2766}
2767
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002768static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2769 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002770{
2771 return 0;
2772}
2773
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002774static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2775 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002776{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002777 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778}
2779
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002780static int out_get_presentation_position(const struct audio_stream_out *stream,
2781 uint64_t *frames, struct timespec *timestamp)
2782{
2783 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002784 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002785 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002786
Eric Laurenta1478072015-09-21 17:21:52 -07002787 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002788
Eric Laurent949a0892013-09-20 09:20:13 -07002789 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2790 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002791 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002792 compress_get_tstamp(out->compr, &dsp_frames,
2793 &out->sample_rate);
2794 ALOGVV("%s rendered frames %ld sample_rate %d",
2795 __func__, dsp_frames, out->sample_rate);
2796 *frames = dsp_frames;
2797 ret = 0;
2798 /* this is the best we can do */
2799 clock_gettime(CLOCK_MONOTONIC, timestamp);
2800 }
2801 } else {
2802 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002803 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002804 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2805 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002806 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002807 // This adjustment accounts for buffering after app processor.
2808 // It is based on estimated DSP latency per use case, rather than exact.
2809 signed_frames -=
2810 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2811
Eric Laurent949a0892013-09-20 09:20:13 -07002812 // It would be unusual for this value to be negative, but check just in case ...
2813 if (signed_frames >= 0) {
2814 *frames = signed_frames;
2815 ret = 0;
2816 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002817 }
2818 }
2819 }
2820
2821 pthread_mutex_unlock(&out->lock);
2822
2823 return ret;
2824}
2825
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002826static int out_set_callback(struct audio_stream_out *stream,
2827 stream_callback_t callback, void *cookie)
2828{
2829 struct stream_out *out = (struct stream_out *)stream;
2830
2831 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002832 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002833 out->offload_callback = callback;
2834 out->offload_cookie = cookie;
2835 pthread_mutex_unlock(&out->lock);
2836 return 0;
2837}
2838
2839static int out_pause(struct audio_stream_out* stream)
2840{
2841 struct stream_out *out = (struct stream_out *)stream;
2842 int status = -ENOSYS;
2843 ALOGV("%s", __func__);
2844 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002845 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2847 status = compress_pause(out->compr);
2848 out->offload_state = OFFLOAD_STATE_PAUSED;
2849 }
2850 pthread_mutex_unlock(&out->lock);
2851 }
2852 return status;
2853}
2854
2855static int out_resume(struct audio_stream_out* stream)
2856{
2857 struct stream_out *out = (struct stream_out *)stream;
2858 int status = -ENOSYS;
2859 ALOGV("%s", __func__);
2860 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2861 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002862 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002863 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2864 status = compress_resume(out->compr);
2865 out->offload_state = OFFLOAD_STATE_PLAYING;
2866 }
2867 pthread_mutex_unlock(&out->lock);
2868 }
2869 return status;
2870}
2871
2872static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2873{
2874 struct stream_out *out = (struct stream_out *)stream;
2875 int status = -ENOSYS;
2876 ALOGV("%s", __func__);
2877 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002878 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2880 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2881 else
2882 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2883 pthread_mutex_unlock(&out->lock);
2884 }
2885 return status;
2886}
2887
2888static int out_flush(struct audio_stream_out* stream)
2889{
2890 struct stream_out *out = (struct stream_out *)stream;
2891 ALOGV("%s", __func__);
2892 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002893 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894 stop_compressed_output_l(out);
2895 pthread_mutex_unlock(&out->lock);
2896 return 0;
2897 }
2898 return -ENOSYS;
2899}
2900
Eric Laurent0e46adf2016-12-16 12:49:24 -08002901static int out_stop(const struct audio_stream_out* stream)
2902{
2903 struct stream_out *out = (struct stream_out *)stream;
2904 struct audio_device *adev = out->dev;
2905 int ret = -ENOSYS;
2906
2907 ALOGV("%s", __func__);
2908 pthread_mutex_lock(&adev->lock);
2909 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2910 out->playback_started && out->pcm != NULL) {
2911 pcm_stop(out->pcm);
2912 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002913 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002914 }
2915 pthread_mutex_unlock(&adev->lock);
2916 return ret;
2917}
2918
2919static int out_start(const struct audio_stream_out* stream)
2920{
2921 struct stream_out *out = (struct stream_out *)stream;
2922 struct audio_device *adev = out->dev;
2923 int ret = -ENOSYS;
2924
2925 ALOGV("%s", __func__);
2926 pthread_mutex_lock(&adev->lock);
2927 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2928 !out->playback_started && out->pcm != NULL) {
2929 ret = start_output_stream(out);
2930 if (ret == 0) {
2931 out->playback_started = true;
2932 }
2933 }
2934 pthread_mutex_unlock(&adev->lock);
2935 return ret;
2936}
2937
Phil Burkbc991042017-02-24 08:06:44 -08002938/*
2939 * Modify config->period_count based on min_size_frames
2940 */
2941static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2942{
2943 int periodCountRequested = (min_size_frames + config->period_size - 1)
2944 / config->period_size;
2945 int periodCount = MMAP_PERIOD_COUNT_MIN;
2946
2947 ALOGV("%s original config.period_size = %d config.period_count = %d",
2948 __func__, config->period_size, config->period_count);
2949
2950 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2951 periodCount *= 2;
2952 }
2953 config->period_count = periodCount;
2954
2955 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2956}
2957
Eric Laurent0e46adf2016-12-16 12:49:24 -08002958static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2959 int32_t min_size_frames,
2960 struct audio_mmap_buffer_info *info)
2961{
2962 struct stream_out *out = (struct stream_out *)stream;
2963 struct audio_device *adev = out->dev;
2964 int ret = 0;
2965 unsigned int offset1;
2966 unsigned int frames1;
2967 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002968 uint32_t mmap_size;
2969 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002970
2971 ALOGV("%s", __func__);
2972 pthread_mutex_lock(&adev->lock);
2973
2974 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002975 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002976 ret = -EINVAL;
2977 goto exit;
2978 }
2979 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002980 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002981 ret = -ENOSYS;
2982 goto exit;
2983 }
2984 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2985 if (out->pcm_device_id < 0) {
2986 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2987 __func__, out->pcm_device_id, out->usecase);
2988 ret = -EINVAL;
2989 goto exit;
2990 }
Phil Burkbc991042017-02-24 08:06:44 -08002991
2992 adjust_mmap_period_count(&out->config, min_size_frames);
2993
Eric Laurent0e46adf2016-12-16 12:49:24 -08002994 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2995 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2996 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2997 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2998 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2999 step = "open";
3000 ret = -ENODEV;
3001 goto exit;
3002 }
3003 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3004 if (ret < 0) {
3005 step = "begin";
3006 goto exit;
3007 }
3008 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003009 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003010 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003011 ret = platform_get_mmap_data_fd(adev->platform,
3012 out->pcm_device_id, 0 /*playback*/,
3013 &info->shared_memory_fd,
3014 &mmap_size);
3015 if (ret < 0) {
3016 // Fall back to non exclusive mode
3017 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3018 } else {
3019 if (mmap_size < buffer_size) {
3020 step = "mmap";
3021 goto exit;
3022 }
3023 // FIXME: indicate exclusive mode support by returning a negative buffer size
3024 info->buffer_size_frames *= -1;
3025 }
3026 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003027
3028 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3029 if (ret < 0) {
3030 step = "commit";
3031 goto exit;
3032 }
Phil Burkbc991042017-02-24 08:06:44 -08003033
3034 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003035 ret = 0;
3036
3037 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3038 __func__, info->shared_memory_address, info->buffer_size_frames);
3039
3040exit:
3041 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003042 if (out->pcm == NULL) {
3043 ALOGE("%s: %s - %d", __func__, step, ret);
3044 } else {
3045 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003046 pcm_close(out->pcm);
3047 out->pcm = NULL;
3048 }
3049 }
3050 pthread_mutex_unlock(&adev->lock);
3051 return ret;
3052}
3053
3054static int out_get_mmap_position(const struct audio_stream_out *stream,
3055 struct audio_mmap_position *position)
3056{
3057 struct stream_out *out = (struct stream_out *)stream;
3058 ALOGVV("%s", __func__);
3059 if (position == NULL) {
3060 return -EINVAL;
3061 }
3062 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
3063 return -ENOSYS;
3064 }
3065 if (out->pcm == NULL) {
3066 return -ENOSYS;
3067 }
3068
3069 struct timespec ts = { 0, 0 };
3070 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
3071 if (ret < 0) {
3072 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
3073 return ret;
3074 }
Andy Hungfc044e12017-03-20 09:24:22 -07003075 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003076 return 0;
3077}
3078
3079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080/** audio_stream_in implementation **/
3081static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3082{
3083 struct stream_in *in = (struct stream_in *)stream;
3084
3085 return in->config.rate;
3086}
3087
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003088static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089{
3090 return -ENOSYS;
3091}
3092
3093static size_t in_get_buffer_size(const struct audio_stream *stream)
3094{
3095 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003096 return in->config.period_size * in->af_period_multiplier *
3097 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098}
3099
3100static uint32_t in_get_channels(const struct audio_stream *stream)
3101{
3102 struct stream_in *in = (struct stream_in *)stream;
3103
3104 return in->channel_mask;
3105}
3106
vivek mehta4ed66e62016-04-15 23:33:34 -07003107static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108{
vivek mehta4ed66e62016-04-15 23:33:34 -07003109 struct stream_in *in = (struct stream_in *)stream;
3110 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111}
3112
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003113static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114{
3115 return -ENOSYS;
3116}
3117
3118static int in_standby(struct audio_stream *stream)
3119{
3120 struct stream_in *in = (struct stream_in *)stream;
3121 struct audio_device *adev = in->dev;
3122 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003123 bool do_stop = true;
3124
Eric Laurent994a6932013-07-17 11:51:42 -07003125 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003126
3127 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003128
3129 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003130 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003131 audio_extn_sound_trigger_stop_lab(in);
3132 in->standby = true;
3133 }
3134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003136 if (adev->adm_deregister_stream)
3137 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3138
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003139 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003141 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003142 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003143 in->capture_started = false;
3144 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003145 if (in->pcm) {
3146 pcm_close(in->pcm);
3147 in->pcm = NULL;
3148 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003149 adev->enable_voicerx = false;
3150 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003151 if (do_stop) {
3152 status = stop_input_stream(in);
3153 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003154 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 }
3156 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003157 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158 return status;
3159}
3160
Andy Hungd13f0d32017-06-12 13:58:37 -07003161static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162{
Andy Hungd13f0d32017-06-12 13:58:37 -07003163 struct stream_in *in = (struct stream_in *)stream;
3164
3165 // We try to get the lock for consistency,
3166 // but it isn't necessary for these variables.
3167 // If we're not in standby, we may be blocked on a read.
3168 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3169 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3170 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3171 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3172
3173 if (locked) {
3174 pthread_mutex_unlock(&in->lock);
3175 }
3176
3177 // dump error info
3178 (void)error_log_dump(
3179 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180 return 0;
3181}
3182
3183static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3184{
3185 struct stream_in *in = (struct stream_in *)stream;
3186 struct audio_device *adev = in->dev;
3187 struct str_parms *parms;
3188 char *str;
3189 char value[32];
3190 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003191 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192
Eric Laurent994a6932013-07-17 11:51:42 -07003193 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194 parms = str_parms_create_str(kvpairs);
3195
3196 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3197
Eric Laurenta1478072015-09-21 17:21:52 -07003198 lock_input_stream(in);
3199
Eric Laurent150dbfe2013-02-27 14:31:02 -08003200 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201 if (ret >= 0) {
3202 val = atoi(value);
3203 /* no audio source uses val == 0 */
3204 if ((in->source != val) && (val != 0)) {
3205 in->source = val;
3206 }
3207 }
3208
3209 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211 if (ret >= 0) {
3212 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003213 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003214
3215 // Workaround: If routing to an non existing usb device, fail gracefully
3216 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003217 int card;
3218 if (audio_is_usb_in_device(val) &&
3219 (card = get_alive_usb_card(parms)) >= 0) {
3220
3221 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003222 status = -ENOSYS;
3223 } else {
3224
3225 in->device = val;
3226 /* If recording is in progress, change the tx device to new device */
3227 if (!in->standby) {
3228 ALOGV("update input routing change");
3229 // inform adm before actual routing to prevent glitches.
3230 if (adev->adm_on_routing_change) {
3231 adev->adm_on_routing_change(adev->adm_data,
3232 in->capture_handle);
3233 }
3234 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003235 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237 }
3238 }
3239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003241 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242
3243 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003244 ALOGV("%s: exit: status(%d)", __func__, status);
3245 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003246}
3247
Haynes Mathew George569b7482017-05-08 14:44:27 -07003248static char* in_get_parameters(const struct audio_stream *stream,
3249 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003251 struct stream_in *in = (struct stream_in *)stream;
3252 struct str_parms *query = str_parms_create_str(keys);
3253 char *str;
3254 struct str_parms *reply = str_parms_create();
3255 bool replied = false;
3256
3257 ALOGV("%s: enter: keys - %s", __func__, keys);
3258 replied |= stream_get_parameter_channels(query, reply,
3259 &in->supported_channel_masks[0]);
3260 replied |= stream_get_parameter_formats(query, reply,
3261 &in->supported_formats[0]);
3262 replied |= stream_get_parameter_rates(query, reply,
3263 &in->supported_sample_rates[0]);
3264 if (replied) {
3265 str = str_parms_to_str(reply);
3266 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003267 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003268 }
3269 str_parms_destroy(query);
3270 str_parms_destroy(reply);
3271 ALOGV("%s: exit: returns - %s", __func__, str);
3272 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273}
3274
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003275static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003277 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278}
3279
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003280static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3281{
3282 if (!stream || !parms)
3283 return;
3284
3285 struct stream_in *in = (struct stream_in *)stream;
3286 struct audio_device *adev = in->dev;
3287
3288 card_status_t status;
3289 int card;
3290 if (parse_snd_card_status(parms, &card, &status) < 0)
3291 return;
3292
3293 pthread_mutex_lock(&adev->lock);
3294 bool valid_cb = (card == adev->snd_card);
3295 pthread_mutex_unlock(&adev->lock);
3296
3297 if (!valid_cb)
3298 return;
3299
3300 lock_input_stream(in);
3301 if (in->card_status != status)
3302 in->card_status = status;
3303 pthread_mutex_unlock(&in->lock);
3304
3305 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3306 use_case_table[in->usecase],
3307 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3308
3309 // a better solution would be to report error back to AF and let
3310 // it put the stream to standby
3311 if (status == CARD_STATUS_OFFLINE)
3312 in_standby(&in->stream.common);
3313
3314 return;
3315}
3316
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003317static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3318 size_t bytes)
3319{
3320 struct stream_in *in = (struct stream_in *)stream;
3321 struct audio_device *adev = in->dev;
3322 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003323 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003324 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325
Eric Laurenta1478072015-09-21 17:21:52 -07003326 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003327 const size_t frame_size = audio_stream_in_frame_size(stream);
3328 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003329
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003330 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003331 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003332 /* Read from sound trigger HAL */
3333 audio_extn_sound_trigger_read(in, buffer, bytes);
3334 pthread_mutex_unlock(&in->lock);
3335 return bytes;
3336 }
3337
Eric Laurent0e46adf2016-12-16 12:49:24 -08003338 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3339 ret = -ENOSYS;
3340 goto exit;
3341 }
3342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003344 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003346 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 goto exit;
3349 }
3350 in->standby = 0;
3351 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352
Andy Hungd13f0d32017-06-12 13:58:37 -07003353 // errors that occur here are read errors.
3354 error_code = ERROR_CODE_READ;
3355
Haynes Mathew George03c40102016-01-29 17:57:48 -08003356 //what's the duration requested by the client?
3357 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3358 in->config.rate;
3359 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003360
Haynes Mathew George03c40102016-01-29 17:57:48 -08003361 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003363 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003364 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003365 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003366 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003367 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003368 if (ret < 0) {
3369 ALOGE("Failed to read w/err %s", strerror(errno));
3370 ret = -errno;
3371 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003372 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3373 if (bytes % 4 == 0) {
3374 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3375 int_buf_stream = buffer;
3376 for (size_t itt=0; itt < bytes/4 ; itt++) {
3377 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003378 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003379 } else {
3380 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3381 ret = -EINVAL;
3382 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003383 }
3384 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385 }
3386
Haynes Mathew George03c40102016-01-29 17:57:48 -08003387 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 /*
3390 * Instead of writing zeroes here, we could trust the hardware
3391 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003392 * 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 -08003393 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003394 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003396 in->frames_muted += frames;
3397 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398
3399exit:
3400 pthread_mutex_unlock(&in->lock);
3401
3402 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003403 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404 in_standby(&in->stream.common);
3405 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003406 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003407 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003408 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003409 }
3410 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003411 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 }
3413 return bytes;
3414}
3415
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003416static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417{
3418 return 0;
3419}
3420
Andy Hung6ebe5962016-01-15 17:46:57 -08003421static int in_get_capture_position(const struct audio_stream_in *stream,
3422 int64_t *frames, int64_t *time)
3423{
3424 if (stream == NULL || frames == NULL || time == NULL) {
3425 return -EINVAL;
3426 }
3427 struct stream_in *in = (struct stream_in *)stream;
3428 int ret = -ENOSYS;
3429
3430 lock_input_stream(in);
3431 if (in->pcm) {
3432 struct timespec timestamp;
3433 unsigned int avail;
3434 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3435 *frames = in->frames_read + avail;
3436 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3437 ret = 0;
3438 }
3439 }
3440 pthread_mutex_unlock(&in->lock);
3441 return ret;
3442}
3443
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003444static int add_remove_audio_effect(const struct audio_stream *stream,
3445 effect_handle_t effect,
3446 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003447{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003448 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003449 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003450 int status = 0;
3451 effect_descriptor_t desc;
3452
3453 status = (*effect)->get_descriptor(effect, &desc);
3454 if (status != 0)
3455 return status;
3456
Eric Laurenta1478072015-09-21 17:21:52 -07003457 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003458 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003459 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003460 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003461 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003462 in->enable_aec != enable &&
3463 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3464 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003465 if (!enable)
3466 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003467 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3468 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3469 adev->enable_voicerx = enable;
3470 struct audio_usecase *usecase;
3471 struct listnode *node;
3472 list_for_each(node, &adev->usecase_list) {
3473 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003474 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003475 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003476 }
3477 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003478 if (!in->standby)
3479 select_devices(in->dev, in->usecase);
3480 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003481 if (in->enable_ns != enable &&
3482 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3483 in->enable_ns = enable;
3484 if (!in->standby)
3485 select_devices(in->dev, in->usecase);
3486 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003487 pthread_mutex_unlock(&in->dev->lock);
3488 pthread_mutex_unlock(&in->lock);
3489
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 return 0;
3491}
3492
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003493static int in_add_audio_effect(const struct audio_stream *stream,
3494 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495{
Eric Laurent994a6932013-07-17 11:51:42 -07003496 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003497 return add_remove_audio_effect(stream, effect, true);
3498}
3499
3500static int in_remove_audio_effect(const struct audio_stream *stream,
3501 effect_handle_t effect)
3502{
Eric Laurent994a6932013-07-17 11:51:42 -07003503 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003504 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505}
3506
Eric Laurent0e46adf2016-12-16 12:49:24 -08003507static int in_stop(const struct audio_stream_in* stream)
3508{
3509 struct stream_in *in = (struct stream_in *)stream;
3510 struct audio_device *adev = in->dev;
3511
3512 int ret = -ENOSYS;
3513 ALOGV("%s", __func__);
3514 pthread_mutex_lock(&adev->lock);
3515 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3516 in->capture_started && in->pcm != NULL) {
3517 pcm_stop(in->pcm);
3518 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003519 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003520 }
3521 pthread_mutex_unlock(&adev->lock);
3522 return ret;
3523}
3524
3525static int in_start(const struct audio_stream_in* stream)
3526{
3527 struct stream_in *in = (struct stream_in *)stream;
3528 struct audio_device *adev = in->dev;
3529 int ret = -ENOSYS;
3530
3531 ALOGV("%s in %p", __func__, in);
3532 pthread_mutex_lock(&adev->lock);
3533 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3534 !in->capture_started && in->pcm != NULL) {
3535 if (!in->capture_started) {
3536 ret = start_input_stream(in);
3537 if (ret == 0) {
3538 in->capture_started = true;
3539 }
3540 }
3541 }
3542 pthread_mutex_unlock(&adev->lock);
3543 return ret;
3544}
3545
3546static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3547 int32_t min_size_frames,
3548 struct audio_mmap_buffer_info *info)
3549{
3550 struct stream_in *in = (struct stream_in *)stream;
3551 struct audio_device *adev = in->dev;
3552 int ret = 0;
3553 unsigned int offset1;
3554 unsigned int frames1;
3555 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003556 uint32_t mmap_size;
3557 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003558
3559 pthread_mutex_lock(&adev->lock);
3560 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003561
Eric Laurent0e46adf2016-12-16 12:49:24 -08003562 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003563 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003564 ret = -EINVAL;
3565 goto exit;
3566 }
3567 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003568 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003569 ALOGV("%s in %p", __func__, in);
3570 ret = -ENOSYS;
3571 goto exit;
3572 }
3573 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3574 if (in->pcm_device_id < 0) {
3575 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3576 __func__, in->pcm_device_id, in->usecase);
3577 ret = -EINVAL;
3578 goto exit;
3579 }
Phil Burkbc991042017-02-24 08:06:44 -08003580
3581 adjust_mmap_period_count(&in->config, min_size_frames);
3582
Eric Laurent0e46adf2016-12-16 12:49:24 -08003583 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3584 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3585 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3586 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3587 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3588 step = "open";
3589 ret = -ENODEV;
3590 goto exit;
3591 }
3592
3593 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3594 if (ret < 0) {
3595 step = "begin";
3596 goto exit;
3597 }
3598 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003599 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003600 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003601 ret = platform_get_mmap_data_fd(adev->platform,
3602 in->pcm_device_id, 1 /*capture*/,
3603 &info->shared_memory_fd,
3604 &mmap_size);
3605 if (ret < 0) {
3606 // Fall back to non exclusive mode
3607 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3608 } else {
3609 if (mmap_size < buffer_size) {
3610 step = "mmap";
3611 goto exit;
3612 }
3613 // FIXME: indicate exclusive mode support by returning a negative buffer size
3614 info->buffer_size_frames *= -1;
3615 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003616
Haynes Mathew George96483a22017-03-28 14:52:47 -07003617 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003618
3619 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3620 if (ret < 0) {
3621 step = "commit";
3622 goto exit;
3623 }
3624
Phil Burkbc991042017-02-24 08:06:44 -08003625 in->standby = false;
3626 ret = 0;
3627
Eric Laurent0e46adf2016-12-16 12:49:24 -08003628 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3629 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003630
3631exit:
3632 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003633 if (in->pcm == NULL) {
3634 ALOGE("%s: %s - %d", __func__, step, ret);
3635 } else {
3636 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003637 pcm_close(in->pcm);
3638 in->pcm = NULL;
3639 }
3640 }
3641 pthread_mutex_unlock(&adev->lock);
3642 return ret;
3643}
3644
3645static int in_get_mmap_position(const struct audio_stream_in *stream,
3646 struct audio_mmap_position *position)
3647{
3648 struct stream_in *in = (struct stream_in *)stream;
3649 ALOGVV("%s", __func__);
3650 if (position == NULL) {
3651 return -EINVAL;
3652 }
3653 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3654 return -ENOSYS;
3655 }
3656 if (in->pcm == NULL) {
3657 return -ENOSYS;
3658 }
3659 struct timespec ts = { 0, 0 };
3660 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3661 if (ret < 0) {
3662 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3663 return ret;
3664 }
Andy Hungfc044e12017-03-20 09:24:22 -07003665 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003666 return 0;
3667}
3668
3669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003670static int adev_open_output_stream(struct audio_hw_device *dev,
3671 audio_io_handle_t handle,
3672 audio_devices_t devices,
3673 audio_output_flags_t flags,
3674 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003675 struct audio_stream_out **stream_out,
3676 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677{
3678 struct audio_device *adev = (struct audio_device *)dev;
3679 struct stream_out *out;
3680 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003681 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3682 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3683 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3684 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685
Andy Hungd9653bd2017-08-01 19:31:39 -07003686 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3687 return -ENOSYS;
3688 }
3689
Eric Laurent994a6932013-07-17 11:51:42 -07003690 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691 __func__, config->sample_rate, config->channel_mask, devices, flags);
3692 *stream_out = NULL;
3693 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3694
3695 if (devices == AUDIO_DEVICE_NONE)
3696 devices = AUDIO_DEVICE_OUT_SPEAKER;
3697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698 out->flags = flags;
3699 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003700 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003701 out->format = config->format;
3702 out->sample_rate = config->sample_rate;
3703 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3704 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003705 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706
3707 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003708 if (audio_is_linear_pcm(out->format) &&
3709 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003710 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003711 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003712 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003713 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003714 if (config->sample_rate == 0)
3715 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3716 if (config->channel_mask == 0)
3717 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3718 if (config->format == AUDIO_FORMAT_DEFAULT)
3719 config->format = AUDIO_FORMAT_PCM_16_BIT;
3720 } else if (is_usb_dev) {
3721 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3722 &config->format,
3723 &out->supported_formats[0],
3724 MAX_SUPPORTED_FORMATS,
3725 &config->channel_mask,
3726 &out->supported_channel_masks[0],
3727 MAX_SUPPORTED_CHANNEL_MASKS,
3728 &config->sample_rate,
3729 &out->supported_sample_rates[0],
3730 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003731 ALOGV("plugged dev USB ret %d", ret);
3732 } else {
3733 ret = -1;
3734 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003735 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003736 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003737 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003738
Haynes Mathew George569b7482017-05-08 14:44:27 -07003739 out->channel_mask = config->channel_mask;
3740 out->sample_rate = config->sample_rate;
3741 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003742 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3743 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003744 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003746 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003747 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3748 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003749 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003750 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003751 pthread_mutex_lock(&adev->lock);
3752 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3753 pthread_mutex_unlock(&adev->lock);
3754
3755 // reject offload during card offline to allow
3756 // fallback to s/w paths
3757 if (offline) {
3758 ret = -ENODEV;
3759 goto error_open;
3760 }
3761
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003762 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3763 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3764 ALOGE("%s: Unsupported Offload information", __func__);
3765 ret = -EINVAL;
3766 goto error_open;
3767 }
3768 if (!is_supported_format(config->offload_info.format)) {
3769 ALOGE("%s: Unsupported audio format", __func__);
3770 ret = -EINVAL;
3771 goto error_open;
3772 }
3773
3774 out->compr_config.codec = (struct snd_codec *)
3775 calloc(1, sizeof(struct snd_codec));
3776
3777 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3778 if (config->offload_info.channel_mask)
3779 out->channel_mask = config->offload_info.channel_mask;
3780 else if (config->channel_mask)
3781 out->channel_mask = config->channel_mask;
3782 out->format = config->offload_info.format;
3783 out->sample_rate = config->offload_info.sample_rate;
3784
3785 out->stream.set_callback = out_set_callback;
3786 out->stream.pause = out_pause;
3787 out->stream.resume = out_resume;
3788 out->stream.drain = out_drain;
3789 out->stream.flush = out_flush;
3790
3791 out->compr_config.codec->id =
3792 get_snd_codec_id(config->offload_info.format);
3793 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3794 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003795 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003796 out->compr_config.codec->bit_rate =
3797 config->offload_info.bit_rate;
3798 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003799 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003800 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3801
3802 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3803 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003804
3805 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003806 create_offload_callback_thread(out);
3807 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3808 __func__, config->offload_info.version,
3809 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003810 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003811 switch (config->sample_rate) {
3812 case 8000:
3813 case 16000:
3814 case 48000:
3815 out->sample_rate = config->sample_rate;
3816 break;
3817 default:
3818 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003819 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003820 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003821 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3822 out->config = pcm_config_afe_proxy_playback;
3823 adev->voice_tx_output = out;
Eric Laurentad2dde92017-09-20 18:27:31 -07003824 } else if (out->flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
3825 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
vivek mehtaa68fea62017-06-08 19:04:02 -07003826 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07003827 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3828 out->config = pcm_config_voip;
3829 out->config.format = pcm_format_from_audio_format(config->format);
3830 out->config.rate = config->sample_rate;
vivek mehtaa68fea62017-06-08 19:04:02 -07003831 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3832 config->sample_rate,
3833 config->format,
3834 out->config.channels,
3835 false /*is_low_latency*/);
3836 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3837 out->config.period_size = buffer_size / frame_size;
3838 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3839 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003841 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3842 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3843 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003844 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3845 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3846 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003847 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3848 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003849 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003850 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003851 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3852 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3853 out->config = pcm_config_mmap_playback;
3854 out->stream.start = out_start;
3855 out->stream.stop = out_stop;
3856 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3857 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003858 } else {
3859 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3860 out->config = pcm_config_low_latency;
3861 }
3862 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003863 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003864 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003865 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003867
3868 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3869 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3870 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3871 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3872 __func__, config->sample_rate, config->format, config->channel_mask);
3873 config->sample_rate = out->sample_rate;
3874 config->format = out->format;
3875 config->channel_mask = out->channel_mask;
3876 ret = -EINVAL;
3877 goto error_open;
3878 }
3879
Andy Hung6fcba9c2014-03-18 11:53:32 -07003880 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3881 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003882
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003883 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003884 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003885 adev->primary_output = out;
3886 else {
3887 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003888 ret = -EEXIST;
3889 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003890 }
3891 }
3892
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893 /* Check if this usecase is already existing */
3894 pthread_mutex_lock(&adev->lock);
3895 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3896 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003898 ret = -EEXIST;
3899 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900 }
3901 pthread_mutex_unlock(&adev->lock);
3902
3903 out->stream.common.get_sample_rate = out_get_sample_rate;
3904 out->stream.common.set_sample_rate = out_set_sample_rate;
3905 out->stream.common.get_buffer_size = out_get_buffer_size;
3906 out->stream.common.get_channels = out_get_channels;
3907 out->stream.common.get_format = out_get_format;
3908 out->stream.common.set_format = out_set_format;
3909 out->stream.common.standby = out_standby;
3910 out->stream.common.dump = out_dump;
3911 out->stream.common.set_parameters = out_set_parameters;
3912 out->stream.common.get_parameters = out_get_parameters;
3913 out->stream.common.add_audio_effect = out_add_audio_effect;
3914 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3915 out->stream.get_latency = out_get_latency;
3916 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003917#ifdef NO_AUDIO_OUT
3918 out->stream.write = out_write_for_no_output;
3919#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003921#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003922 out->stream.get_render_position = out_get_render_position;
3923 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003924 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003925
Eric Laurent0e46adf2016-12-16 12:49:24 -08003926 if (out->realtime)
3927 out->af_period_multiplier = af_period_multiplier;
3928 else
3929 out->af_period_multiplier = 1;
3930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003932 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003933 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003935 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003936 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003937 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003939 config->format = out->stream.common.get_format(&out->stream.common);
3940 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3941 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3942
Andy Hunga452b0a2017-03-15 14:51:15 -07003943 out->error_log = error_log_create(
3944 ERROR_LOG_ENTRIES,
3945 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3946
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003947 /*
3948 By locking output stream before registering, we allow the callback
3949 to update stream's state only after stream's initial state is set to
3950 adev state.
3951 */
3952 lock_output_stream(out);
3953 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3954 pthread_mutex_lock(&adev->lock);
3955 out->card_status = adev->card_status;
3956 pthread_mutex_unlock(&adev->lock);
3957 pthread_mutex_unlock(&out->lock);
3958
vivek mehta4a824772017-06-08 19:05:49 -07003959 stream_app_type_cfg_init(&out->app_type_cfg);
3960
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003961 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003962
Eric Laurent994a6932013-07-17 11:51:42 -07003963 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003965
3966error_open:
3967 free(out);
3968 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003969 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003970 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971}
3972
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003973static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003974 struct audio_stream_out *stream)
3975{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003976 struct stream_out *out = (struct stream_out *)stream;
3977 struct audio_device *adev = out->dev;
3978
Eric Laurent994a6932013-07-17 11:51:42 -07003979 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003980
3981 // must deregister from sndmonitor first to prevent races
3982 // between the callback and close_stream
3983 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003985 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3986 destroy_offload_callback_thread(out);
3987
3988 if (out->compr_config.codec != NULL)
3989 free(out->compr_config.codec);
3990 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003991
3992 if (adev->voice_tx_output == out)
3993 adev->voice_tx_output = NULL;
3994
Andy Hunga452b0a2017-03-15 14:51:15 -07003995 error_log_destroy(out->error_log);
3996 out->error_log = NULL;
3997
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003998 pthread_cond_destroy(&out->cond);
3999 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004001 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004002}
4003
4004static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4005{
4006 struct audio_device *adev = (struct audio_device *)dev;
4007 struct str_parms *parms;
4008 char *str;
4009 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004010 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004011 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004012 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004013
Joe Onorato188b6222016-03-01 11:02:27 -08004014 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004015
4016 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004017
4018 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004019 status = voice_set_parameters(adev, parms);
4020 if (status != 0) {
4021 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022 }
4023
4024 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4025 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004026 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004027 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4028 adev->bluetooth_nrec = true;
4029 else
4030 adev->bluetooth_nrec = false;
4031 }
4032
4033 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4034 if (ret >= 0) {
4035 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4036 adev->screen_off = false;
4037 else
4038 adev->screen_off = true;
4039 }
4040
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004041 ret = str_parms_get_int(parms, "rotation", &val);
4042 if (ret >= 0) {
4043 bool reverse_speakers = false;
4044 switch(val) {
4045 // FIXME: note that the code below assumes that the speakers are in the correct placement
4046 // relative to the user when the device is rotated 90deg from its default rotation. This
4047 // assumption is device-specific, not platform-specific like this code.
4048 case 270:
4049 reverse_speakers = true;
4050 break;
4051 case 0:
4052 case 90:
4053 case 180:
4054 break;
4055 default:
4056 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004057 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004058 }
Eric Laurent03f09432014-03-25 18:09:11 -07004059 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004060 // check and set swap
4061 // - check if orientation changed and speaker active
4062 // - set rotation and cache the rotation value
4063 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004064 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004065 }
4066
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004067 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4068 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004069 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004070 }
4071
David Linee3fe402017-03-13 10:00:42 -07004072 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4073 if (ret >= 0) {
4074 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004075 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004076 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4077 if (ret >= 0) {
4078 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004079 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004080 }
Eric Laurent99dab492017-06-17 15:19:08 -07004081 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004082 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4083 if (ret >= 0) {
4084 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004085 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004086 }
4087 }
4088 }
4089
4090 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4091 if (ret >= 0) {
4092 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004093 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004094 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4095 if (ret >= 0) {
4096 const int card = atoi(value);
4097
Eric Laurent99dab492017-06-17 15:19:08 -07004098 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004099 }
Eric Laurent99dab492017-06-17 15:19:08 -07004100 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004101 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4102 if (ret >= 0) {
4103 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004104 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004105 }
4106 }
4107 }
4108
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004109 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004110done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004112 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004113 ALOGV("%s: exit with code(%d)", __func__, status);
4114 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004115}
4116
4117static char* adev_get_parameters(const struct audio_hw_device *dev,
4118 const char *keys)
4119{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004120 struct audio_device *adev = (struct audio_device *)dev;
4121 struct str_parms *reply = str_parms_create();
4122 struct str_parms *query = str_parms_create_str(keys);
4123 char *str;
4124
4125 pthread_mutex_lock(&adev->lock);
4126
4127 voice_get_parameters(adev, query, reply);
4128 str = str_parms_to_str(reply);
4129 str_parms_destroy(query);
4130 str_parms_destroy(reply);
4131
4132 pthread_mutex_unlock(&adev->lock);
4133 ALOGV("%s: exit: returns - %s", __func__, str);
4134 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004135}
4136
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004137static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138{
4139 return 0;
4140}
4141
Haynes Mathew George5191a852013-09-11 14:19:36 -07004142static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4143{
4144 int ret;
4145 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004146
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004147 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4148
Haynes Mathew George5191a852013-09-11 14:19:36 -07004149 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004150 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004151 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004152
Haynes Mathew George5191a852013-09-11 14:19:36 -07004153 return ret;
4154}
4155
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004156static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157{
4158 return -ENOSYS;
4159}
4160
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004161static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4162 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163{
4164 return -ENOSYS;
4165}
4166
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004167static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168{
4169 return -ENOSYS;
4170}
4171
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004172static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173{
4174 return -ENOSYS;
4175}
4176
4177static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4178{
4179 struct audio_device *adev = (struct audio_device *)dev;
4180
4181 pthread_mutex_lock(&adev->lock);
4182 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004183 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004184 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004185 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4186 voice_is_in_call(adev)) {
4187 voice_stop_call(adev);
4188 adev->current_call_output = NULL;
4189 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004190 }
4191 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004192
4193 audio_extn_extspk_set_mode(adev->extspk, mode);
4194
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195 return 0;
4196}
4197
4198static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4199{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004200 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202
Eric Laurent2bafff12016-03-17 12:17:23 -07004203 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004204 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004205 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4206 ret = audio_extn_hfp_set_mic_mute(adev, state);
4207 } else {
4208 ret = voice_set_mic_mute(adev, state);
4209 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004210 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004211 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004212
4213 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214}
4215
4216static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4217{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004218 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219 return 0;
4220}
4221
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004222static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 const struct audio_config *config)
4224{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004225 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226
Eric Laurent74b55762017-07-09 17:04:53 -07004227 /* Don't know if USB HIFI in this context so use true to be conservative */
4228 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4229 true /*is_usb_hifi */) != 0)
4230 return 0;
4231
vivek mehtaa68fea62017-06-08 19:04:02 -07004232 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4233 config->sample_rate, config->format,
4234 channel_count,
4235 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236}
4237
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004238static bool adev_input_allow_hifi_record(struct audio_device *adev,
4239 audio_devices_t devices,
4240 audio_input_flags_t flags,
4241 audio_source_t source) {
4242 const bool allowed = true;
4243
4244 if (!audio_is_usb_in_device(devices))
4245 return !allowed;
4246
4247 switch (flags) {
4248 case AUDIO_INPUT_FLAG_NONE:
4249 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4250 break;
4251 default:
4252 return !allowed;
4253 }
4254
4255 switch (source) {
4256 case AUDIO_SOURCE_DEFAULT:
4257 case AUDIO_SOURCE_MIC:
4258 case AUDIO_SOURCE_UNPROCESSED:
4259 break;
4260 default:
4261 return !allowed;
4262 }
4263
4264 switch (adev->mode) {
4265 case 0:
4266 break;
4267 default:
4268 return !allowed;
4269 }
4270
4271 return allowed;
4272}
4273
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004274static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004275 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276 audio_devices_t devices,
4277 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004278 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004279 audio_input_flags_t flags,
4280 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004281 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004282{
4283 struct audio_device *adev = (struct audio_device *)dev;
4284 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004285 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004286 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004287 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004288 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004289 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4290 devices,
4291 flags,
4292 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004293 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004294 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004295
Andy Hungd9653bd2017-08-01 19:31:39 -07004296 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4297 return -ENOSYS;
4298 }
4299
Eric Laurent74b55762017-07-09 17:04:53 -07004300 if (!(is_usb_dev && may_use_hifi_record)) {
4301 if (config->sample_rate == 0)
4302 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4303 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4304 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4305 if (config->format == AUDIO_FORMAT_DEFAULT)
4306 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004307
Eric Laurent74b55762017-07-09 17:04:53 -07004308 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4309
4310 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4311 return -EINVAL;
4312 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004314 if (audio_extn_tfa_98xx_is_supported() &&
4315 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004316 return -EINVAL;
4317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4319
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004320 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004321 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004322
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004323 in->stream.common.get_sample_rate = in_get_sample_rate;
4324 in->stream.common.set_sample_rate = in_set_sample_rate;
4325 in->stream.common.get_buffer_size = in_get_buffer_size;
4326 in->stream.common.get_channels = in_get_channels;
4327 in->stream.common.get_format = in_get_format;
4328 in->stream.common.set_format = in_set_format;
4329 in->stream.common.standby = in_standby;
4330 in->stream.common.dump = in_dump;
4331 in->stream.common.set_parameters = in_set_parameters;
4332 in->stream.common.get_parameters = in_get_parameters;
4333 in->stream.common.add_audio_effect = in_add_audio_effect;
4334 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4335 in->stream.set_gain = in_set_gain;
4336 in->stream.read = in_read;
4337 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004338 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004339
4340 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004341 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004343 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004344 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004345 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346
Haynes Mathew George569b7482017-05-08 14:44:27 -07004347 if (is_usb_dev && may_use_hifi_record) {
4348 /* HiFi record selects an appropriate format, channel, rate combo
4349 depending on sink capabilities*/
4350 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4351 &config->format,
4352 &in->supported_formats[0],
4353 MAX_SUPPORTED_FORMATS,
4354 &config->channel_mask,
4355 &in->supported_channel_masks[0],
4356 MAX_SUPPORTED_CHANNEL_MASKS,
4357 &config->sample_rate,
4358 &in->supported_sample_rates[0],
4359 MAX_SUPPORTED_SAMPLE_RATES);
4360 if (ret != 0) {
4361 ret = -EINVAL;
4362 goto err_open;
4363 }
Eric Laurent74b55762017-07-09 17:04:53 -07004364 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004365 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004366 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004367 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4368 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4369 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4370 bool ret_error = false;
4371 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4372 from HAL is 8_24
4373 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4374 8_24 return error indicating supported format is 8_24
4375 *> In case of any other source requesting 24 bit or float return error
4376 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004377
vivek mehta57ff9b52016-04-28 14:13:08 -07004378 on error flinger will retry with supported format passed
4379 */
4380 if (source != AUDIO_SOURCE_UNPROCESSED) {
4381 config->format = AUDIO_FORMAT_PCM_16_BIT;
4382 ret_error = true;
4383 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4384 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4385 ret_error = true;
4386 }
4387
4388 if (ret_error) {
4389 ret = -EINVAL;
4390 goto err_open;
4391 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004392 }
4393
vivek mehta57ff9b52016-04-28 14:13:08 -07004394 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004395 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004397 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004398 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4399 if (config->sample_rate == 0)
4400 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4401 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4402 config->sample_rate != 8000) {
4403 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4404 ret = -EINVAL;
4405 goto err_open;
4406 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004407
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004408 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4409 config->format = AUDIO_FORMAT_PCM_16_BIT;
4410 ret = -EINVAL;
4411 goto err_open;
4412 }
4413
4414 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4415 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004416 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004417 } else if (is_usb_dev && may_use_hifi_record) {
4418 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4419 in->config = pcm_config_audio_capture;
4420 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004421 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4422 config->sample_rate,
4423 config->format,
4424 channel_count,
4425 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004426 in->config.period_size = buffer_size / frame_size;
4427 in->config.rate = config->sample_rate;
4428 in->af_period_multiplier = 1;
4429 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004430 } else {
4431 in->usecase = USECASE_AUDIO_RECORD;
4432 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004433 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004434 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004435#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004436 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004437#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004438 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004439 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004440 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004441 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004442 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4443 config->sample_rate,
4444 config->format,
4445 channel_count,
4446 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004447 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004448 in->config.rate = config->sample_rate;
4449 in->af_period_multiplier = 1;
4450 } else {
4451 // period size is left untouched for rt mode playback
4452 in->config = pcm_config_audio_capture_rt;
4453 in->af_period_multiplier = af_period_multiplier;
4454 }
4455 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4456 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004457 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004458 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4459 in->config = pcm_config_mmap_capture;
4460 in->stream.start = in_start;
4461 in->stream.stop = in_stop;
4462 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4463 in->stream.get_mmap_position = in_get_mmap_position;
4464 in->af_period_multiplier = 1;
4465 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004466 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004467 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004468 (config->sample_rate == 8000 ||
4469 config->sample_rate == 16000 ||
4470 config->sample_rate == 32000 ||
4471 config->sample_rate == 48000) &&
4472 channel_count == 1) {
4473 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4474 in->config = pcm_config_audio_capture;
4475 frame_size = audio_stream_in_frame_size(&in->stream);
4476 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4477 config->sample_rate,
4478 config->format,
4479 channel_count, false /*is_low_latency*/);
4480 in->config.period_size = buffer_size / frame_size;
4481 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4482 in->config.rate = config->sample_rate;
4483 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004484 } else {
4485 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004486 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004487 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4488 config->sample_rate,
4489 config->format,
4490 channel_count,
4491 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004492 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004493 in->config.rate = config->sample_rate;
4494 in->af_period_multiplier = 1;
4495 }
4496 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4497 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004498 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004501 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004502
Andy Hungd13f0d32017-06-12 13:58:37 -07004503 in->error_log = error_log_create(
4504 ERROR_LOG_ENTRIES,
4505 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4506
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004507 /* This stream could be for sound trigger lab,
4508 get sound trigger pcm if present */
4509 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004510
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004511 lock_input_stream(in);
4512 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4513 pthread_mutex_lock(&adev->lock);
4514 in->card_status = adev->card_status;
4515 pthread_mutex_unlock(&adev->lock);
4516 pthread_mutex_unlock(&in->lock);
4517
vivek mehta4a824772017-06-08 19:05:49 -07004518 stream_app_type_cfg_init(&in->app_type_cfg);
4519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004520 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004521 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004522 return 0;
4523
4524err_open:
4525 free(in);
4526 *stream_in = NULL;
4527 return ret;
4528}
4529
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004530static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531 struct audio_stream_in *stream)
4532{
Andy Hungd13f0d32017-06-12 13:58:37 -07004533 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004534 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004535
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004536 // must deregister from sndmonitor first to prevent races
4537 // between the callback and close_stream
4538 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004539 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004540
4541 error_log_destroy(in->error_log);
4542 in->error_log = NULL;
4543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544 free(stream);
4545
4546 return;
4547}
4548
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004549static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004550{
4551 return 0;
4552}
4553
Andy Hung31aca912014-03-20 17:14:59 -07004554/* verifies input and output devices and their capabilities.
4555 *
4556 * This verification is required when enabling extended bit-depth or
4557 * sampling rates, as not all qcom products support it.
4558 *
4559 * Suitable for calling only on initialization such as adev_open().
4560 * It fills the audio_device use_case_table[] array.
4561 *
4562 * Has a side-effect that it needs to configure audio routing / devices
4563 * in order to power up the devices and read the device parameters.
4564 * It does not acquire any hw device lock. Should restore the devices
4565 * back to "normal state" upon completion.
4566 */
4567static int adev_verify_devices(struct audio_device *adev)
4568{
4569 /* enumeration is a bit difficult because one really wants to pull
4570 * the use_case, device id, etc from the hidden pcm_device_table[].
4571 * In this case there are the following use cases and device ids.
4572 *
4573 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4574 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004575 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004576 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4577 * [USECASE_AUDIO_RECORD] = {0, 0},
4578 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4579 * [USECASE_VOICE_CALL] = {2, 2},
4580 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004581 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004582 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4583 */
4584
4585 /* should be the usecases enabled in adev_open_input_stream() */
4586 static const int test_in_usecases[] = {
4587 USECASE_AUDIO_RECORD,
4588 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4589 };
4590 /* should be the usecases enabled in adev_open_output_stream()*/
4591 static const int test_out_usecases[] = {
4592 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4593 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4594 };
4595 static const usecase_type_t usecase_type_by_dir[] = {
4596 PCM_PLAYBACK,
4597 PCM_CAPTURE,
4598 };
4599 static const unsigned flags_by_dir[] = {
4600 PCM_OUT,
4601 PCM_IN,
4602 };
4603
4604 size_t i;
4605 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004606 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004607 char info[512]; /* for possible debug info */
4608
4609 for (dir = 0; dir < 2; ++dir) {
4610 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4611 const unsigned flags_dir = flags_by_dir[dir];
4612 const size_t testsize =
4613 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4614 const int *testcases =
4615 dir ? test_in_usecases : test_out_usecases;
4616 const audio_devices_t audio_device =
4617 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4618
4619 for (i = 0; i < testsize; ++i) {
4620 const audio_usecase_t audio_usecase = testcases[i];
4621 int device_id;
4622 snd_device_t snd_device;
4623 struct pcm_params **pparams;
4624 struct stream_out out;
4625 struct stream_in in;
4626 struct audio_usecase uc_info;
4627 int retval;
4628
4629 pparams = &adev->use_case_table[audio_usecase];
4630 pcm_params_free(*pparams); /* can accept null input */
4631 *pparams = NULL;
4632
4633 /* find the device ID for the use case (signed, for error) */
4634 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4635 if (device_id < 0)
4636 continue;
4637
4638 /* prepare structures for device probing */
4639 memset(&uc_info, 0, sizeof(uc_info));
4640 uc_info.id = audio_usecase;
4641 uc_info.type = usecase_type;
4642 if (dir) {
4643 adev->active_input = &in;
4644 memset(&in, 0, sizeof(in));
4645 in.device = audio_device;
4646 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4647 uc_info.stream.in = &in;
4648 } else {
4649 adev->active_input = NULL;
4650 }
4651 memset(&out, 0, sizeof(out));
4652 out.devices = audio_device; /* only field needed in select_devices */
4653 uc_info.stream.out = &out;
4654 uc_info.devices = audio_device;
4655 uc_info.in_snd_device = SND_DEVICE_NONE;
4656 uc_info.out_snd_device = SND_DEVICE_NONE;
4657 list_add_tail(&adev->usecase_list, &uc_info.list);
4658
4659 /* select device - similar to start_(in/out)put_stream() */
4660 retval = select_devices(adev, audio_usecase);
4661 if (retval >= 0) {
4662 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4663#if LOG_NDEBUG == 0
4664 if (*pparams) {
4665 ALOGV("%s: (%s) card %d device %d", __func__,
4666 dir ? "input" : "output", card_id, device_id);
4667 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004668 } else {
4669 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4670 }
4671#endif
4672 }
4673
4674 /* deselect device - similar to stop_(in/out)put_stream() */
4675 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004676 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004677 /* 2. Disable the rx device */
4678 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004679 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004680 list_remove(&uc_info.list);
4681 }
4682 }
4683 adev->active_input = NULL; /* restore adev state */
4684 return 0;
4685}
4686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687static int adev_close(hw_device_t *device)
4688{
Andy Hung31aca912014-03-20 17:14:59 -07004689 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004690 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004691
4692 if (!adev)
4693 return 0;
4694
4695 pthread_mutex_lock(&adev_init_lock);
4696
4697 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004698 audio_extn_snd_mon_unregister_listener(adev);
4699 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004700 audio_route_free(adev->audio_route);
4701 free(adev->snd_dev_ref_cnt);
4702 platform_deinit(adev->platform);
4703 audio_extn_extspk_deinit(adev->extspk);
4704 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004705 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004706 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4707 pcm_params_free(adev->use_case_table[i]);
4708 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004709 if (adev->adm_deinit)
4710 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004711 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004712 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004713
4714 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004716 return 0;
4717}
4718
Glenn Kasten4f993392014-05-14 07:30:48 -07004719/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4720 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4721 * just that it _might_ work.
4722 */
4723static int period_size_is_plausible_for_low_latency(int period_size)
4724{
4725 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004726 case 48:
4727 case 96:
4728 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004729 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004730 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004731 case 240:
4732 case 320:
4733 case 480:
4734 return 1;
4735 default:
4736 return 0;
4737 }
4738}
4739
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004740static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4741{
4742 int card;
4743 card_status_t status;
4744
4745 if (!parms)
4746 return;
4747
4748 if (parse_snd_card_status(parms, &card, &status) < 0)
4749 return;
4750
4751 pthread_mutex_lock(&adev->lock);
4752 bool valid_cb = (card == adev->snd_card);
4753 if (valid_cb) {
4754 if (adev->card_status != status) {
4755 adev->card_status = status;
4756 platform_snd_card_update(adev->platform, status);
4757 }
4758 }
4759 pthread_mutex_unlock(&adev->lock);
4760 return;
4761}
4762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763static int adev_open(const hw_module_t *module, const char *name,
4764 hw_device_t **device)
4765{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004766 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767
Eric Laurent2bafff12016-03-17 12:17:23 -07004768 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004770 pthread_mutex_lock(&adev_init_lock);
4771 if (audio_device_ref_count != 0) {
4772 *device = &adev->device.common;
4773 audio_device_ref_count++;
4774 ALOGV("%s: returning existing instance of adev", __func__);
4775 ALOGV("%s: exit", __func__);
4776 pthread_mutex_unlock(&adev_init_lock);
4777 return 0;
4778 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004779 adev = calloc(1, sizeof(struct audio_device));
4780
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004781 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004783 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4784 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4785 adev->device.common.module = (struct hw_module_t *)module;
4786 adev->device.common.close = adev_close;
4787
4788 adev->device.init_check = adev_init_check;
4789 adev->device.set_voice_volume = adev_set_voice_volume;
4790 adev->device.set_master_volume = adev_set_master_volume;
4791 adev->device.get_master_volume = adev_get_master_volume;
4792 adev->device.set_master_mute = adev_set_master_mute;
4793 adev->device.get_master_mute = adev_get_master_mute;
4794 adev->device.set_mode = adev_set_mode;
4795 adev->device.set_mic_mute = adev_set_mic_mute;
4796 adev->device.get_mic_mute = adev_get_mic_mute;
4797 adev->device.set_parameters = adev_set_parameters;
4798 adev->device.get_parameters = adev_get_parameters;
4799 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4800 adev->device.open_output_stream = adev_open_output_stream;
4801 adev->device.close_output_stream = adev_close_output_stream;
4802 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004804 adev->device.close_input_stream = adev_close_input_stream;
4805 adev->device.dump = adev_dump;
4806
4807 /* Set the default route before the PCM stream is opened */
4808 pthread_mutex_lock(&adev->lock);
4809 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004810 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004811 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004812 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004813 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004814 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004815 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004816 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004817 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004818 pthread_mutex_unlock(&adev->lock);
4819
4820 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004821 adev->platform = platform_init(adev);
4822 if (!adev->platform) {
4823 free(adev->snd_dev_ref_cnt);
4824 free(adev);
4825 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4826 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004827 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004828 return -EINVAL;
4829 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004830 adev->extspk = audio_extn_extspk_init(adev);
4831
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004832 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4833 if (adev->visualizer_lib == NULL) {
4834 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4835 } else {
4836 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4837 adev->visualizer_start_output =
4838 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4839 "visualizer_hal_start_output");
4840 adev->visualizer_stop_output =
4841 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4842 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004843 }
4844
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004845 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4846 if (adev->offload_effects_lib == NULL) {
4847 ALOGW("%s: DLOPEN failed for %s", __func__,
4848 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4849 } else {
4850 ALOGV("%s: DLOPEN successful for %s", __func__,
4851 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4852 adev->offload_effects_start_output =
4853 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4854 "offload_effects_bundle_hal_start_output");
4855 adev->offload_effects_stop_output =
4856 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4857 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004858 }
4859
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004860 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4861 if (adev->adm_lib == NULL) {
4862 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4863 } else {
4864 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4865 adev->adm_init = (adm_init_t)
4866 dlsym(adev->adm_lib, "adm_init");
4867 adev->adm_deinit = (adm_deinit_t)
4868 dlsym(adev->adm_lib, "adm_deinit");
4869 adev->adm_register_input_stream = (adm_register_input_stream_t)
4870 dlsym(adev->adm_lib, "adm_register_input_stream");
4871 adev->adm_register_output_stream = (adm_register_output_stream_t)
4872 dlsym(adev->adm_lib, "adm_register_output_stream");
4873 adev->adm_deregister_stream = (adm_deregister_stream_t)
4874 dlsym(adev->adm_lib, "adm_deregister_stream");
4875 adev->adm_request_focus = (adm_request_focus_t)
4876 dlsym(adev->adm_lib, "adm_request_focus");
4877 adev->adm_abandon_focus = (adm_abandon_focus_t)
4878 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004879 adev->adm_set_config = (adm_set_config_t)
4880 dlsym(adev->adm_lib, "adm_set_config");
4881 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4882 dlsym(adev->adm_lib, "adm_request_focus_v2");
4883 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4884 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4885 adev->adm_on_routing_change = (adm_on_routing_change_t)
4886 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004887 }
4888
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004889 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004890 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004891
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004892 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004893
Andy Hung31aca912014-03-20 17:14:59 -07004894 if (k_enable_extended_precision)
4895 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004896
Glenn Kasten4f993392014-05-14 07:30:48 -07004897 char value[PROPERTY_VALUE_MAX];
4898 int trial;
4899 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4900 trial = atoi(value);
4901 if (period_size_is_plausible_for_low_latency(trial)) {
4902 pcm_config_low_latency.period_size = trial;
4903 pcm_config_low_latency.start_threshold = trial / 4;
4904 pcm_config_low_latency.avail_min = trial / 4;
4905 configured_low_latency_capture_period_size = trial;
4906 }
4907 }
4908 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4909 trial = atoi(value);
4910 if (period_size_is_plausible_for_low_latency(trial)) {
4911 configured_low_latency_capture_period_size = trial;
4912 }
4913 }
4914
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004915 // commented as full set of app type cfg is sent from platform
4916 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004917 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004918
4919 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4920 af_period_multiplier = atoi(value);
4921 if (af_period_multiplier < 0) {
4922 af_period_multiplier = 2;
4923 } else if (af_period_multiplier > 4) {
4924 af_period_multiplier = 4;
4925 }
4926 ALOGV("new period_multiplier = %d", af_period_multiplier);
4927 }
4928
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004929 audio_extn_tfa_98xx_init(adev);
4930
vivek mehta1a9b7c02015-06-25 11:49:38 -07004931 pthread_mutex_unlock(&adev_init_lock);
4932
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004933 if (adev->adm_init)
4934 adev->adm_data = adev->adm_init();
4935
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004936 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004937 audio_extn_snd_mon_init();
4938 pthread_mutex_lock(&adev->lock);
4939 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4940 adev->card_status = CARD_STATUS_ONLINE;
4941 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004942 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004943
Eric Laurent2bafff12016-03-17 12:17:23 -07004944 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004945 return 0;
4946}
4947
4948static struct hw_module_methods_t hal_module_methods = {
4949 .open = adev_open,
4950};
4951
4952struct audio_module HAL_MODULE_INFO_SYM = {
4953 .common = {
4954 .tag = HARDWARE_MODULE_TAG,
4955 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4956 .hal_api_version = HARDWARE_HAL_API_VERSION,
4957 .id = AUDIO_HARDWARE_MODULE_ID,
4958 .name = "QCOM Audio HAL",
4959 .author = "Code Aurora Forum",
4960 .methods = &hal_module_methods,
4961 },
4962};