blob: d7b9dc9d4dcc3a86d0acb814879c97ceea924f10 [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 mehta1a9b7c02015-06-25 11:49:38 -0700446__attribute__ ((visibility ("default")))
447bool audio_hw_send_gain_dep_calibration(int level) {
448 bool ret_val = false;
449 ALOGV("%s: enter ... ", __func__);
450
451 pthread_mutex_lock(&adev_init_lock);
452
453 if (adev != NULL && adev->platform != NULL) {
454 pthread_mutex_lock(&adev->lock);
455 ret_val = platform_send_gain_dep_cal(adev->platform, level);
456 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700457
458 // if cal set fails, cache level info
459 // if cal set succeds, reset known last cal set
460 if (!ret_val)
461 last_known_cal_step = level;
462 else if (last_known_cal_step != -1)
463 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700464 } 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;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001167
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001168 usecase = get_usecase_from_list(adev, uc_id);
1169 if (usecase == NULL) {
1170 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1171 return -EINVAL;
1172 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001173
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001174 if ((usecase->type == VOICE_CALL) ||
1175 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001176 out_snd_device = platform_get_output_snd_device(adev->platform,
1177 usecase->stream.out->devices);
1178 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 usecase->devices = usecase->stream.out->devices;
1180 } else {
1181 /*
1182 * If the voice call is active, use the sound devices of voice call usecase
1183 * so that it would not result any device switch. All the usecases will
1184 * be switched to new device when select_devices() is called for voice call
1185 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001186 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001188 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001189 vc_usecase = get_usecase_from_list(adev,
1190 get_voice_usecase_id_from_list(adev));
1191 if ((vc_usecase != NULL) &&
1192 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1193 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 in_snd_device = vc_usecase->in_snd_device;
1195 out_snd_device = vc_usecase->out_snd_device;
1196 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001197 } else if (audio_extn_hfp_is_active(adev)) {
1198 hfp_ucid = audio_extn_hfp_get_usecase();
1199 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1200 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1201 in_snd_device = hfp_usecase->in_snd_device;
1202 out_snd_device = hfp_usecase->out_snd_device;
1203 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001204 }
1205 if (usecase->type == PCM_PLAYBACK) {
1206 usecase->devices = usecase->stream.out->devices;
1207 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001208 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001209 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001211 if (usecase->stream.out == adev->primary_output &&
1212 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001213 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1214 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001215 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001216 select_devices(adev, adev->active_input->usecase);
1217 }
1218 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001219 } else if (usecase->type == PCM_CAPTURE) {
1220 usecase->devices = usecase->stream.in->device;
1221 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001222 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001223 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001224 if (adev->active_input &&
1225 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1226 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001227 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001228 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1229 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1230 } else if (adev->primary_output) {
1231 out_device = adev->primary_output->devices;
1232 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001233 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001234 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001235 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001236 }
1237 }
1238
1239 if (out_snd_device == usecase->out_snd_device &&
1240 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001241 return 0;
1242 }
1243
Eric Laurent2bafff12016-03-17 12:17:23 -07001244 if (out_snd_device != SND_DEVICE_NONE &&
1245 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1246 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1247 __func__,
1248 use_case_table[uc_id],
1249 adev->last_logged_snd_device[uc_id][0],
1250 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1251 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1252 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1253 -1,
1254 out_snd_device,
1255 platform_get_snd_device_name(out_snd_device),
1256 platform_get_snd_device_acdb_id(out_snd_device));
1257 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1258 }
1259 if (in_snd_device != SND_DEVICE_NONE &&
1260 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1261 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1262 __func__,
1263 use_case_table[uc_id],
1264 adev->last_logged_snd_device[uc_id][1],
1265 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1266 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1267 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1268 -1,
1269 in_snd_device,
1270 platform_get_snd_device_name(in_snd_device),
1271 platform_get_snd_device_acdb_id(in_snd_device));
1272 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1273 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001274
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001275 /*
1276 * Limitation: While in call, to do a device switch we need to disable
1277 * and enable both RX and TX devices though one of them is same as current
1278 * device.
1279 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001280 if ((usecase->type == VOICE_CALL) &&
1281 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1282 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001283 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001284 /* Disable sidetone only if voice call already exists */
1285 if (voice_is_call_state_active(adev))
1286 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001287 }
1288
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001289 /* Disable current sound devices */
1290 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001291 disable_audio_route(adev, usecase);
1292 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001293 }
1294
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001295 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001296 disable_audio_route(adev, usecase);
1297 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001298 }
1299
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001300 /* Applicable only on the targets that has external modem.
1301 * New device information should be sent to modem before enabling
1302 * the devices to reduce in-call device switch time.
1303 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001304 if ((usecase->type == VOICE_CALL) &&
1305 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1306 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001307 status = platform_switch_voice_call_enable_device_config(adev->platform,
1308 out_snd_device,
1309 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001310 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001311
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001312 /* Enable new sound devices */
1313 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001314 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001315 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001316 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001317 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318 }
1319
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001320 if (in_snd_device != SND_DEVICE_NONE) {
1321 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001322 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001323 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001324
Eric Laurentb23d5282013-05-14 15:27:20 -07001325 if (usecase->type == VOICE_CALL)
1326 status = platform_switch_voice_call_device_post(adev->platform,
1327 out_snd_device,
1328 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001329
sangwoo170731f2013-06-08 15:36:36 +09001330 usecase->in_snd_device = in_snd_device;
1331 usecase->out_snd_device = out_snd_device;
1332
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001333 audio_extn_tfa_98xx_set_mode();
1334
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001335 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001336
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001337 /* Applicable only on the targets that has external modem.
1338 * Enable device command should be sent to modem only after
1339 * enabling voice call mixer controls
1340 */
vivek mehta765eb642015-08-07 19:46:06 -07001341 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001342 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1343 out_snd_device,
1344 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001345 /* Enable sidetone only if voice call already exists */
1346 if (voice_is_call_state_active(adev))
1347 voice_set_sidetone(adev, out_snd_device, true);
1348 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350 return status;
1351}
1352
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001353static int stop_input_stream(struct stream_in *in)
1354{
1355 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356 struct audio_usecase *uc_info;
1357 struct audio_device *adev = in->dev;
1358
Eric Laurent994a6932013-07-17 11:51:42 -07001359 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001360 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001361
1362 if (adev->active_input) {
1363 if (adev->active_input->usecase == in->usecase) {
1364 adev->active_input = NULL;
1365 } else {
1366 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1367 __func__,
1368 use_case_table[adev->active_input->usecase],
1369 use_case_table[in->usecase]);
1370 }
1371 }
1372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 uc_info = get_usecase_from_list(adev, in->usecase);
1374 if (uc_info == NULL) {
1375 ALOGE("%s: Could not find the usecase (%d) in the list",
1376 __func__, in->usecase);
1377 return -EINVAL;
1378 }
1379
vivek mehta781065c2017-04-04 12:55:01 -07001380 /* Close in-call recording streams */
1381 voice_check_and_stop_incall_rec_usecase(adev, in);
1382
Eric Laurent150dbfe2013-02-27 14:31:02 -08001383 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001384 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001385
1386 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001387 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001389 list_remove(&uc_info->list);
1390 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001391
Eric Laurent994a6932013-07-17 11:51:42 -07001392 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001393 return ret;
1394}
1395
1396int start_input_stream(struct stream_in *in)
1397{
1398 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001399 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001400 struct audio_usecase *uc_info;
1401 struct audio_device *adev = in->dev;
1402
Eric Laurent994a6932013-07-17 11:51:42 -07001403 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001404
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001405 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1406 return -EIO;
1407
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001408 if (in->card_status == CARD_STATUS_OFFLINE ||
1409 adev->card_status == CARD_STATUS_OFFLINE) {
1410 ALOGW("in->card_status or adev->card_status offline, try again");
1411 ret = -EAGAIN;
1412 goto error_config;
1413 }
1414
vivek mehta781065c2017-04-04 12:55:01 -07001415 /* Check if source matches incall recording usecase criteria */
1416 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1417 if (ret)
1418 goto error_config;
1419 else
1420 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1421
Eric Laurentb23d5282013-05-14 15:27:20 -07001422 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001423 if (in->pcm_device_id < 0) {
1424 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1425 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001426 ret = -EINVAL;
1427 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001429
1430 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1432 uc_info->id = in->usecase;
1433 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001434 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435 uc_info->devices = in->device;
1436 uc_info->in_snd_device = SND_DEVICE_NONE;
1437 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001439 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001440
1441 audio_extn_perf_lock_acquire();
1442
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001443 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001444
Eric Laurent0e46adf2016-12-16 12:49:24 -08001445 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001446 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001447 ALOGE("%s: pcm stream not ready", __func__);
1448 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001449 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001450 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001451 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001452 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1453 goto error_open;
1454 }
1455 } else {
1456 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1457 unsigned int pcm_open_retry_count = 0;
1458
1459 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1460 flags |= PCM_MMAP | PCM_NOIRQ;
1461 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1462 } else if (in->realtime) {
1463 flags |= PCM_MMAP | PCM_NOIRQ;
1464 }
1465
1466 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1467 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1468
1469 while (1) {
1470 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1471 flags, &in->config);
1472 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1473 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1474 if (in->pcm != NULL) {
1475 pcm_close(in->pcm);
1476 in->pcm = NULL;
1477 }
1478 if (pcm_open_retry_count-- == 0) {
1479 ret = -EIO;
1480 goto error_open;
1481 }
1482 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1483 continue;
1484 }
1485 break;
1486 }
1487
1488 ALOGV("%s: pcm_prepare", __func__);
1489 ret = pcm_prepare(in->pcm);
1490 if (ret < 0) {
1491 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001492 pcm_close(in->pcm);
1493 in->pcm = NULL;
1494 goto error_open;
1495 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001496 if (in->realtime) {
1497 ret = pcm_start(in->pcm);
1498 if (ret < 0) {
1499 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1500 pcm_close(in->pcm);
1501 in->pcm = NULL;
1502 goto error_open;
1503 }
1504 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001505 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001506 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001507 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001508 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001509
Eric Laurent0e46adf2016-12-16 12:49:24 -08001510 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001511
1512error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001513 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001514 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001515
1516error_config:
1517 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001518 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001519 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001520}
1521
Eric Laurenta1478072015-09-21 17:21:52 -07001522void lock_input_stream(struct stream_in *in)
1523{
1524 pthread_mutex_lock(&in->pre_lock);
1525 pthread_mutex_lock(&in->lock);
1526 pthread_mutex_unlock(&in->pre_lock);
1527}
1528
1529void lock_output_stream(struct stream_out *out)
1530{
1531 pthread_mutex_lock(&out->pre_lock);
1532 pthread_mutex_lock(&out->lock);
1533 pthread_mutex_unlock(&out->pre_lock);
1534}
1535
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001536/* must be called with out->lock locked */
1537static int send_offload_cmd_l(struct stream_out* out, int command)
1538{
1539 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1540
1541 ALOGVV("%s %d", __func__, command);
1542
1543 cmd->cmd = command;
1544 list_add_tail(&out->offload_cmd_list, &cmd->node);
1545 pthread_cond_signal(&out->offload_cond);
1546 return 0;
1547}
1548
1549/* must be called iwth out->lock locked */
1550static void stop_compressed_output_l(struct stream_out *out)
1551{
1552 out->offload_state = OFFLOAD_STATE_IDLE;
1553 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001554 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001555 if (out->compr != NULL) {
1556 compress_stop(out->compr);
1557 while (out->offload_thread_blocked) {
1558 pthread_cond_wait(&out->cond, &out->lock);
1559 }
1560 }
1561}
1562
1563static void *offload_thread_loop(void *context)
1564{
1565 struct stream_out *out = (struct stream_out *) context;
1566 struct listnode *item;
1567
1568 out->offload_state = OFFLOAD_STATE_IDLE;
1569 out->playback_started = 0;
1570
1571 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1572 set_sched_policy(0, SP_FOREGROUND);
1573 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1574
1575 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001576 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001577 for (;;) {
1578 struct offload_cmd *cmd = NULL;
1579 stream_callback_event_t event;
1580 bool send_callback = false;
1581
1582 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1583 __func__, list_empty(&out->offload_cmd_list),
1584 out->offload_state);
1585 if (list_empty(&out->offload_cmd_list)) {
1586 ALOGV("%s SLEEPING", __func__);
1587 pthread_cond_wait(&out->offload_cond, &out->lock);
1588 ALOGV("%s RUNNING", __func__);
1589 continue;
1590 }
1591
1592 item = list_head(&out->offload_cmd_list);
1593 cmd = node_to_item(item, struct offload_cmd, node);
1594 list_remove(item);
1595
1596 ALOGVV("%s STATE %d CMD %d out->compr %p",
1597 __func__, out->offload_state, cmd->cmd, out->compr);
1598
1599 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1600 free(cmd);
1601 break;
1602 }
1603
1604 if (out->compr == NULL) {
1605 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001606 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001607 pthread_cond_signal(&out->cond);
1608 continue;
1609 }
1610 out->offload_thread_blocked = true;
1611 pthread_mutex_unlock(&out->lock);
1612 send_callback = false;
1613 switch(cmd->cmd) {
1614 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1615 compress_wait(out->compr, -1);
1616 send_callback = true;
1617 event = STREAM_CBK_EVENT_WRITE_READY;
1618 break;
1619 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001620 compress_next_track(out->compr);
1621 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001622 send_callback = true;
1623 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001624 /* Resend the metadata for next iteration */
1625 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001626 break;
1627 case OFFLOAD_CMD_DRAIN:
1628 compress_drain(out->compr);
1629 send_callback = true;
1630 event = STREAM_CBK_EVENT_DRAIN_READY;
1631 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001632 case OFFLOAD_CMD_ERROR:
1633 send_callback = true;
1634 event = STREAM_CBK_EVENT_ERROR;
1635 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001636 default:
1637 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1638 break;
1639 }
Eric Laurenta1478072015-09-21 17:21:52 -07001640 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001641 out->offload_thread_blocked = false;
1642 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001643 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001644 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001645 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001646 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001647 free(cmd);
1648 }
1649
1650 pthread_cond_signal(&out->cond);
1651 while (!list_empty(&out->offload_cmd_list)) {
1652 item = list_head(&out->offload_cmd_list);
1653 list_remove(item);
1654 free(node_to_item(item, struct offload_cmd, node));
1655 }
1656 pthread_mutex_unlock(&out->lock);
1657
1658 return NULL;
1659}
1660
1661static int create_offload_callback_thread(struct stream_out *out)
1662{
1663 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1664 list_init(&out->offload_cmd_list);
1665 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1666 offload_thread_loop, out);
1667 return 0;
1668}
1669
1670static int destroy_offload_callback_thread(struct stream_out *out)
1671{
Eric Laurenta1478072015-09-21 17:21:52 -07001672 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001673 stop_compressed_output_l(out);
1674 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1675
1676 pthread_mutex_unlock(&out->lock);
1677 pthread_join(out->offload_thread, (void **) NULL);
1678 pthread_cond_destroy(&out->offload_cond);
1679
1680 return 0;
1681}
1682
Eric Laurent07eeafd2013-10-06 12:52:49 -07001683static bool allow_hdmi_channel_config(struct audio_device *adev)
1684{
1685 struct listnode *node;
1686 struct audio_usecase *usecase;
1687 bool ret = true;
1688
1689 list_for_each(node, &adev->usecase_list) {
1690 usecase = node_to_item(node, struct audio_usecase, list);
1691 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1692 /*
1693 * If voice call is already existing, do not proceed further to avoid
1694 * disabling/enabling both RX and TX devices, CSD calls, etc.
1695 * Once the voice call done, the HDMI channels can be configured to
1696 * max channels of remaining use cases.
1697 */
1698 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001699 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001700 __func__);
1701 ret = false;
1702 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001703 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1704 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001705 "no change in HDMI channels", __func__);
1706 ret = false;
1707 break;
1708 }
1709 }
1710 }
1711 return ret;
1712}
1713
1714static int check_and_set_hdmi_channels(struct audio_device *adev,
1715 unsigned int channels)
1716{
1717 struct listnode *node;
1718 struct audio_usecase *usecase;
1719
1720 /* Check if change in HDMI channel config is allowed */
1721 if (!allow_hdmi_channel_config(adev))
1722 return 0;
1723
1724 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001725 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001726 return 0;
1727 }
1728
1729 platform_set_hdmi_channels(adev->platform, channels);
1730 adev->cur_hdmi_channels = channels;
1731
1732 /*
1733 * Deroute all the playback streams routed to HDMI so that
1734 * the back end is deactivated. Note that backend will not
1735 * be deactivated if any one stream is connected to it.
1736 */
1737 list_for_each(node, &adev->usecase_list) {
1738 usecase = node_to_item(node, struct audio_usecase, list);
1739 if (usecase->type == PCM_PLAYBACK &&
1740 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001741 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001742 }
1743 }
1744
1745 /*
1746 * Enable all the streams disabled above. Now the HDMI backend
1747 * will be activated with new channel configuration
1748 */
1749 list_for_each(node, &adev->usecase_list) {
1750 usecase = node_to_item(node, struct audio_usecase, list);
1751 if (usecase->type == PCM_PLAYBACK &&
1752 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001753 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001754 }
1755 }
1756
1757 return 0;
1758}
1759
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760static int stop_output_stream(struct stream_out *out)
1761{
1762 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763 struct audio_usecase *uc_info;
1764 struct audio_device *adev = out->dev;
1765
Eric Laurent994a6932013-07-17 11:51:42 -07001766 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001767 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 uc_info = get_usecase_from_list(adev, out->usecase);
1769 if (uc_info == NULL) {
1770 ALOGE("%s: Could not find the usecase (%d) in the list",
1771 __func__, out->usecase);
1772 return -EINVAL;
1773 }
1774
Haynes Mathew George41f86652014-06-17 14:22:15 -07001775 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1776 if (adev->visualizer_stop_output != NULL)
1777 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1778 if (adev->offload_effects_stop_output != NULL)
1779 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1780 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001781
Eric Laurent150dbfe2013-02-27 14:31:02 -08001782 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001783 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001784
1785 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001786 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001788 list_remove(&uc_info->list);
1789 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790
Eric Laurent0499d4f2014-08-25 22:39:29 -05001791 audio_extn_extspk_update(adev->extspk);
1792
Eric Laurent07eeafd2013-10-06 12:52:49 -07001793 /* Must be called after removing the usecase from list */
1794 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1795 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1796
Eric Laurent994a6932013-07-17 11:51:42 -07001797 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 return ret;
1799}
1800
1801int start_output_stream(struct stream_out *out)
1802{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 struct audio_usecase *uc_info;
1805 struct audio_device *adev = out->dev;
1806
Eric Laurent994a6932013-07-17 11:51:42 -07001807 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001808 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001809
1810 if (out->card_status == CARD_STATUS_OFFLINE ||
1811 adev->card_status == CARD_STATUS_OFFLINE) {
1812 ALOGW("out->card_status or adev->card_status offline, try again");
1813 ret = -EAGAIN;
1814 goto error_config;
1815 }
1816
Eric Laurentb23d5282013-05-14 15:27:20 -07001817 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001818 if (out->pcm_device_id < 0) {
1819 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1820 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001821 ret = -EINVAL;
1822 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 }
1824
1825 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1826 uc_info->id = out->usecase;
1827 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001828 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001829 uc_info->devices = out->devices;
1830 uc_info->in_snd_device = SND_DEVICE_NONE;
1831 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001832
Eric Laurent07eeafd2013-10-06 12:52:49 -07001833 /* This must be called before adding this usecase to the list */
1834 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1835 check_and_set_hdmi_channels(adev, out->config.channels);
1836
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001837 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001839 audio_extn_perf_lock_acquire();
1840
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001841 select_devices(adev, out->usecase);
1842
Eric Laurent0499d4f2014-08-25 22:39:29 -05001843 audio_extn_extspk_update(adev->extspk);
1844
Andy Hung31aca912014-03-20 17:14:59 -07001845 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001846 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001847 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1848 out->pcm = NULL;
1849 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1850 COMPRESS_IN, &out->compr_config);
1851 if (out->compr && !is_compress_ready(out->compr)) {
1852 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1853 compress_close(out->compr);
1854 out->compr = NULL;
1855 ret = -EIO;
1856 goto error_open;
1857 }
1858 if (out->offload_callback)
1859 compress_nonblock(out->compr, out->non_blocking);
1860
1861 if (adev->visualizer_start_output != NULL)
1862 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1863 if (adev->offload_effects_start_output != NULL)
1864 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1865 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001866 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001867 ALOGE("%s: pcm stream not ready", __func__);
1868 goto error_open;
1869 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001870 ret = pcm_start(out->pcm);
1871 if (ret < 0) {
1872 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1873 goto error_open;
1874 }
1875 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001876 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001877 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001878
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001879 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1880 flags |= PCM_MMAP | PCM_NOIRQ;
1881 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001882 } else if (out->realtime) {
1883 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001884 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001885
1886 while (1) {
1887 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1888 flags, &out->config);
1889 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1890 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1891 if (out->pcm != NULL) {
1892 pcm_close(out->pcm);
1893 out->pcm = NULL;
1894 }
1895 if (pcm_open_retry_count-- == 0) {
1896 ret = -EIO;
1897 goto error_open;
1898 }
1899 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1900 continue;
1901 }
1902 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001903 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001904 ALOGV("%s: pcm_prepare", __func__);
1905 if (pcm_is_ready(out->pcm)) {
1906 ret = pcm_prepare(out->pcm);
1907 if (ret < 0) {
1908 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1909 pcm_close(out->pcm);
1910 out->pcm = NULL;
1911 goto error_open;
1912 }
1913 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001914 if (out->realtime) {
1915 ret = pcm_start(out->pcm);
1916 if (ret < 0) {
1917 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1918 pcm_close(out->pcm);
1919 out->pcm = NULL;
1920 goto error_open;
1921 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001922 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001923 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001924 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001925 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001926 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001927 audio_extn_utils_send_app_type_gain(out->dev,
1928 out->app_type_cfg.app_type,
1929 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001930
1931 // consider a scenario where on pause lower layers are tear down.
1932 // so on resume, swap mixer control need to be sent only when
1933 // backend is active, hence rather than sending from enable device
1934 // sending it from start of streamtream
1935
1936 platform_set_swap_channels(adev, true);
1937
Eric Laurent994a6932013-07-17 11:51:42 -07001938 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001939 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001940error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001941 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001943error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001944 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945}
1946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947static int check_input_parameters(uint32_t sample_rate,
1948 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001949 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001951 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1952 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001953 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1954 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001955 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1956 return -EINVAL;
1957 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958
Eric Laurent74b55762017-07-09 17:04:53 -07001959 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1960 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001961 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001962 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001963 return -EINVAL;
1964 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965
1966 switch (sample_rate) {
1967 case 8000:
1968 case 11025:
1969 case 12000:
1970 case 16000:
1971 case 22050:
1972 case 24000:
1973 case 32000:
1974 case 44100:
1975 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001976 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977 break;
1978 default:
vivek mehtadae44712015-07-27 14:13:18 -07001979 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 return -EINVAL;
1981 }
1982
1983 return 0;
1984}
1985
vivek mehtaa68fea62017-06-08 19:04:02 -07001986static size_t get_stream_buffer_size(size_t duration_ms,
1987 uint32_t sample_rate,
1988 audio_format_t format,
1989 int channel_count,
1990 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991{
1992 size_t size = 0;
1993
vivek mehtaa68fea62017-06-08 19:04:02 -07001994 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001995 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001996 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001997
1998 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999
Glenn Kasten4f993392014-05-14 07:30:48 -07002000 /* make sure the size is multiple of 32 bytes
2001 * At 48 kHz mono 16-bit PCM:
2002 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2003 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2004 */
2005 size += 0x1f;
2006 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002007
2008 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009}
2010
2011static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2012{
2013 struct stream_out *out = (struct stream_out *)stream;
2014
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002015 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016}
2017
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002018static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019{
2020 return -ENOSYS;
2021}
2022
2023static size_t out_get_buffer_size(const struct audio_stream *stream)
2024{
2025 struct stream_out *out = (struct stream_out *)stream;
2026
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002027 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2028 return out->compr_config.fragment_size;
2029 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002030 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002031 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032}
2033
2034static uint32_t out_get_channels(const struct audio_stream *stream)
2035{
2036 struct stream_out *out = (struct stream_out *)stream;
2037
2038 return out->channel_mask;
2039}
2040
2041static audio_format_t out_get_format(const struct audio_stream *stream)
2042{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002043 struct stream_out *out = (struct stream_out *)stream;
2044
2045 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002046}
2047
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002048static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049{
2050 return -ENOSYS;
2051}
2052
2053static int out_standby(struct audio_stream *stream)
2054{
2055 struct stream_out *out = (struct stream_out *)stream;
2056 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002057 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058
Eric Laurent994a6932013-07-17 11:51:42 -07002059 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002060 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061
Eric Laurenta1478072015-09-21 17:21:52 -07002062 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002064 if (adev->adm_deregister_stream)
2065 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002066 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002067 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002068 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2069 if (out->pcm) {
2070 pcm_close(out->pcm);
2071 out->pcm = NULL;
2072 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002073 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002074 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002075 out->playback_started = false;
2076 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002077 } else {
2078 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002079 out->gapless_mdata.encoder_delay = 0;
2080 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002081 if (out->compr != NULL) {
2082 compress_close(out->compr);
2083 out->compr = NULL;
2084 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002085 }
Phil Burkbc991042017-02-24 08:06:44 -08002086 if (do_stop) {
2087 stop_output_stream(out);
2088 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002089 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 }
2091 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002092 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093 return 0;
2094}
2095
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002096static int out_on_error(struct audio_stream *stream)
2097{
2098 struct stream_out *out = (struct stream_out *)stream;
2099 struct audio_device *adev = out->dev;
2100 bool do_standby = false;
2101
2102 lock_output_stream(out);
2103 if (!out->standby) {
2104 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2105 stop_compressed_output_l(out);
2106 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2107 } else
2108 do_standby = true;
2109 }
2110 pthread_mutex_unlock(&out->lock);
2111
2112 if (do_standby)
2113 return out_standby(&out->stream.common);
2114
2115 return 0;
2116}
2117
Andy Hung7401c7c2016-09-21 12:41:21 -07002118static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002119{
Andy Hung7401c7c2016-09-21 12:41:21 -07002120 struct stream_out *out = (struct stream_out *)stream;
2121
2122 // We try to get the lock for consistency,
2123 // but it isn't necessary for these variables.
2124 // If we're not in standby, we may be blocked on a write.
2125 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2126 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2127 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2128
2129 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002130 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002131 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002132
2133 // dump error info
2134 (void)error_log_dump(
2135 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137 return 0;
2138}
2139
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002140static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2141{
2142 int ret = 0;
2143 char value[32];
2144 struct compr_gapless_mdata tmp_mdata;
2145
2146 if (!out || !parms) {
2147 return -EINVAL;
2148 }
2149
2150 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2151 if (ret >= 0) {
2152 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2153 } else {
2154 return -EINVAL;
2155 }
2156
2157 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2158 if (ret >= 0) {
2159 tmp_mdata.encoder_padding = atoi(value);
2160 } else {
2161 return -EINVAL;
2162 }
2163
2164 out->gapless_mdata = tmp_mdata;
2165 out->send_new_metadata = 1;
2166 ALOGV("%s new encoder delay %u and padding %u", __func__,
2167 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2168
2169 return 0;
2170}
2171
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002172static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2173{
2174 return out == adev->primary_output || out == adev->voice_tx_output;
2175}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2178{
2179 struct stream_out *out = (struct stream_out *)stream;
2180 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002181 struct audio_usecase *usecase;
2182 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183 struct str_parms *parms;
2184 char value[32];
2185 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002186 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002187 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188
Eric Laurent2e140aa2016-06-30 17:14:46 -07002189 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002190 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191 parms = str_parms_create_str(kvpairs);
2192 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2193 if (ret >= 0) {
2194 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002195 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002196 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002198 /*
2199 * When HDMI cable is unplugged the music playback is paused and
2200 * the policy manager sends routing=0. But the audioflinger
2201 * continues to write data until standby time (3sec).
2202 * As the HDMI core is turned off, the write gets blocked.
2203 * Avoid this by routing audio to speaker until standby.
2204 */
2205 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2206 val == AUDIO_DEVICE_NONE) {
2207 val = AUDIO_DEVICE_OUT_SPEAKER;
2208 }
2209
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002210 audio_devices_t new_dev = val;
2211
2212 // Workaround: If routing to an non existing usb device, fail gracefully
2213 // The routing request will otherwise block during 10 second
2214 if (audio_is_usb_out_device(new_dev) && !audio_extn_usb_alive(adev->snd_card)) {
2215 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d",
2216 adev->snd_card);
2217 pthread_mutex_unlock(&adev->lock);
2218 pthread_mutex_unlock(&out->lock);
2219 status = -ENOSYS;
2220 goto routing_fail;
2221 }
2222
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002223 /*
2224 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002225 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002226 * the select_devices(). But how do we undo this?
2227 *
2228 * For example, music playback is active on headset (deep-buffer usecase)
2229 * and if we go to ringtones and select a ringtone, low-latency usecase
2230 * will be started on headset+speaker. As we can't enable headset+speaker
2231 * and headset devices at the same time, select_devices() switches the music
2232 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2233 * So when the ringtone playback is completed, how do we undo the same?
2234 *
2235 * We are relying on the out_set_parameters() call on deep-buffer output,
2236 * once the ringtone playback is ended.
2237 * NOTE: We should not check if the current devices are same as new devices.
2238 * Because select_devices() must be called to switch back the music
2239 * playback to headset.
2240 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002241 if (new_dev != AUDIO_DEVICE_NONE) {
2242 bool same_dev = out->devices == new_dev;
2243 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002244
Eric Laurenta7657192014-10-09 21:09:33 -07002245 if (output_drives_call(adev, out)) {
2246 if (!voice_is_in_call(adev)) {
2247 if (adev->mode == AUDIO_MODE_IN_CALL) {
2248 adev->current_call_output = out;
2249 ret = voice_start_call(adev);
2250 }
2251 } else {
2252 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002253 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002254 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002255 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002256
2257 if (!out->standby) {
2258 if (!same_dev) {
2259 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002260 // inform adm before actual routing to prevent glitches.
2261 if (adev->adm_on_routing_change) {
2262 adev->adm_on_routing_change(adev->adm_data,
2263 out->handle);
2264 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002265 }
2266 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002267 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002268
2269 // on device switch force swap, lower functions will make sure
2270 // to check if swap is allowed or not.
2271
2272 if (!same_dev)
2273 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002274 }
2275
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002276 }
2277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002279 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002280
2281 /*handles device and call state changes*/
2282 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002283 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002284 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002285
2286 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2287 parse_compress_metadata(out, parms);
2288 }
2289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002290 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002291 ALOGV("%s: exit: code(%d)", __func__, status);
2292 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293}
2294
Haynes Mathew George569b7482017-05-08 14:44:27 -07002295static bool stream_get_parameter_channels(struct str_parms *query,
2296 struct str_parms *reply,
2297 audio_channel_mask_t *supported_channel_masks) {
2298 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002300 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002301 size_t i, j;
2302
2303 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2304 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305 value[0] = '\0';
2306 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002307 while (supported_channel_masks[i] != 0) {
2308 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2309 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310 if (!first) {
2311 strcat(value, "|");
2312 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002313 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 first = false;
2315 break;
2316 }
2317 }
2318 i++;
2319 }
2320 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002321 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002322 return ret >= 0;
2323}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002324
Haynes Mathew George569b7482017-05-08 14:44:27 -07002325static bool stream_get_parameter_formats(struct str_parms *query,
2326 struct str_parms *reply,
2327 audio_format_t *supported_formats) {
2328 int ret = -1;
2329 char value[256];
2330 int i;
2331
2332 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2333 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002334 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002335 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002336 case AUDIO_FORMAT_PCM_16_BIT:
2337 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2338 break;
2339 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2340 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2341 break;
2342 case AUDIO_FORMAT_PCM_32_BIT:
2343 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2344 break;
2345 default:
2346 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002347 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002348 break;
2349 }
2350 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002351 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002352 return ret >= 0;
2353}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002354
Haynes Mathew George569b7482017-05-08 14:44:27 -07002355static bool stream_get_parameter_rates(struct str_parms *query,
2356 struct str_parms *reply,
2357 uint32_t *supported_sample_rates) {
2358
2359 int i;
2360 char value[256];
2361 int ret = -1;
2362 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2363 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002364 value[0] = '\0';
2365 i=0;
2366 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002367 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002368 int avail = sizeof(value) - cursor;
2369 ret = snprintf(value + cursor, avail, "%s%d",
2370 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002371 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002372 if (ret < 0 || ret >= avail) {
2373 // if cursor is at the last element of the array
2374 // overwrite with \0 is duplicate work as
2375 // snprintf already put a \0 in place.
2376 // else
2377 // we had space to write the '|' at value[cursor]
2378 // (which will be overwritten) or no space to fill
2379 // the first element (=> cursor == 0)
2380 value[cursor] = '\0';
2381 break;
2382 }
2383 cursor += ret;
2384 ++i;
2385 }
2386 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2387 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002388 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002389 return ret >= 0;
2390}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002391
Haynes Mathew George569b7482017-05-08 14:44:27 -07002392static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2393{
2394 struct stream_out *out = (struct stream_out *)stream;
2395 struct str_parms *query = str_parms_create_str(keys);
2396 char *str;
2397 struct str_parms *reply = str_parms_create();
2398 bool replied = false;
2399 ALOGV("%s: enter: keys - %s", __func__, keys);
2400
2401 replied |= stream_get_parameter_channels(query, reply,
2402 &out->supported_channel_masks[0]);
2403 replied |= stream_get_parameter_formats(query, reply,
2404 &out->supported_formats[0]);
2405 replied |= stream_get_parameter_rates(query, reply,
2406 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002407 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408 str = str_parms_to_str(reply);
2409 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002410 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411 }
2412 str_parms_destroy(query);
2413 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002414 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415 return str;
2416}
2417
2418static uint32_t out_get_latency(const struct audio_stream_out *stream)
2419{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002420 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421 struct stream_out *out = (struct stream_out *)stream;
2422
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2424 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002425 else if ((out->realtime) ||
2426 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002427 // since the buffer won't be filled up faster than realtime,
2428 // return a smaller number
2429 period_ms = (out->af_period_multiplier * out->config.period_size *
2430 1000) / (out->config.rate);
2431 hw_delay = platform_render_latency(out->usecase)/1000;
2432 return period_ms + hw_delay;
2433 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002434
2435 return (out->config.period_count * out->config.period_size * 1000) /
2436 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437}
2438
2439static int out_set_volume(struct audio_stream_out *stream, float left,
2440 float right)
2441{
Eric Laurenta9024de2013-04-04 09:19:12 -07002442 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002443 int volume[2];
2444
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002445 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002446 /* only take left channel into account: the API is for stereo anyway */
2447 out->muted = (left == 0.0f);
2448 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002449 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2450 const char *mixer_ctl_name = "Compress Playback Volume";
2451 struct audio_device *adev = out->dev;
2452 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2454 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002455 /* try with the control based on device id */
2456 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2457 PCM_PLAYBACK);
2458 char ctl_name[128] = {0};
2459 snprintf(ctl_name, sizeof(ctl_name),
2460 "Compress Playback %d Volume", pcm_device_id);
2461 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2462 if (!ctl) {
2463 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2464 return -EINVAL;
2465 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002466 }
2467 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2468 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2469 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2470 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002471 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002472 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2473 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2474 if (!out->standby) {
2475 // if in standby, cached volume will be sent after stream is opened
2476 audio_extn_utils_send_app_type_gain(out->dev,
2477 out->app_type_cfg.app_type,
2478 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002479 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002480 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002481 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002482
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 return -ENOSYS;
2484}
2485
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002486// note: this call is safe only if the stream_cb is
2487// removed first in close_output_stream (as is done now).
2488static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2489{
2490 if (!stream || !parms)
2491 return;
2492
2493 struct stream_out *out = (struct stream_out *)stream;
2494 struct audio_device *adev = out->dev;
2495
2496 card_status_t status;
2497 int card;
2498 if (parse_snd_card_status(parms, &card, &status) < 0)
2499 return;
2500
2501 pthread_mutex_lock(&adev->lock);
2502 bool valid_cb = (card == adev->snd_card);
2503 pthread_mutex_unlock(&adev->lock);
2504
2505 if (!valid_cb)
2506 return;
2507
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002508 lock_output_stream(out);
2509 if (out->card_status != status)
2510 out->card_status = status;
2511 pthread_mutex_unlock(&out->lock);
2512
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002513 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2514 use_case_table[out->usecase],
2515 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2516
2517 if (status == CARD_STATUS_OFFLINE)
2518 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002519
2520 return;
2521}
2522
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002523#ifdef NO_AUDIO_OUT
2524static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002525 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002526{
2527 struct stream_out *out = (struct stream_out *)stream;
2528
2529 /* No Output device supported other than BT for playback.
2530 * Sleep for the amount of buffer duration
2531 */
Eric Laurenta1478072015-09-21 17:21:52 -07002532 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002533 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2534 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002535 out_get_sample_rate(&out->stream.common));
2536 pthread_mutex_unlock(&out->lock);
2537 return bytes;
2538}
2539#endif
2540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2542 size_t bytes)
2543{
2544 struct stream_out *out = (struct stream_out *)stream;
2545 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002546 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002547 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548
Eric Laurenta1478072015-09-21 17:21:52 -07002549 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002550 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002551 const size_t frame_size = audio_stream_out_frame_size(stream);
2552 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002553
Eric Laurent0e46adf2016-12-16 12:49:24 -08002554 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2555 error_code = ERROR_CODE_WRITE;
2556 goto exit;
2557 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002559 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002560 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002562 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002563 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002564 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002565 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 goto exit;
2567 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002568
2569 if (last_known_cal_step != -1) {
2570 ALOGD("%s: retry previous failed cal level set", __func__);
2571 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2572 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002575 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002576 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002577 if (out->send_new_metadata) {
2578 ALOGVV("send new gapless metadata");
2579 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2580 out->send_new_metadata = 0;
2581 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002582 unsigned int avail;
2583 struct timespec tstamp;
2584 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2585 /* Do not limit write size if the available frames count is unknown */
2586 if (ret != 0) {
2587 avail = bytes;
2588 }
2589 if (avail == 0) {
2590 ret = 0;
2591 } else {
2592 if (avail > bytes) {
2593 avail = bytes;
2594 }
2595 ret = compress_write(out->compr, buffer, avail);
2596 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2597 __func__, avail, ret);
2598 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002599
Eric Laurent6e895242013-09-05 16:10:57 -07002600 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002601 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2602 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002603 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002604 compress_start(out->compr);
2605 out->playback_started = 1;
2606 out->offload_state = OFFLOAD_STATE_PLAYING;
2607 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002608 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002609 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002610 } else {
2611 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002612 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002613 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002614 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002615 return ret;
2616 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002617 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002618 if (out->pcm) {
2619 if (out->muted)
2620 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002621
Eric Laurent0e46adf2016-12-16 12:49:24 -08002622 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002623
Haynes Mathew George03c40102016-01-29 17:57:48 -08002624 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2625 out->config.rate;
2626 request_out_focus(out, ns);
2627
2628 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2629 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002630 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002631 else
2632 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002633
Haynes Mathew George03c40102016-01-29 17:57:48 -08002634 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002635 } else {
2636 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002637 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638 }
2639
2640exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002641 // For PCM we always consume the buffer and return #bytes regardless of ret.
2642 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002643 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002644 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002645 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002646
Andy Hung7401c7c2016-09-21 12:41:21 -07002647 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002648 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002649 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2650 ALOGE_IF(out->pcm != NULL,
2651 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002652 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002653 // usleep not guaranteed for values over 1 second but we don't limit here.
2654 }
2655 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 pthread_mutex_unlock(&out->lock);
2658
2659 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002660 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002661 if (sleeptime_us != 0)
2662 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663 }
2664 return bytes;
2665}
2666
2667static int out_get_render_position(const struct audio_stream_out *stream,
2668 uint32_t *dsp_frames)
2669{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002670 struct stream_out *out = (struct stream_out *)stream;
2671 *dsp_frames = 0;
2672 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002673 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002674 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002675 unsigned long frames = 0;
2676 // TODO: check return value
2677 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2678 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002679 ALOGVV("%s rendered frames %d sample_rate %d",
2680 __func__, *dsp_frames, out->sample_rate);
2681 }
2682 pthread_mutex_unlock(&out->lock);
2683 return 0;
2684 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002685 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686}
2687
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002688static int out_add_audio_effect(const struct audio_stream *stream __unused,
2689 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690{
2691 return 0;
2692}
2693
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002694static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2695 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696{
2697 return 0;
2698}
2699
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002700static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2701 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002703 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704}
2705
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002706static int out_get_presentation_position(const struct audio_stream_out *stream,
2707 uint64_t *frames, struct timespec *timestamp)
2708{
2709 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002710 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002711 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002712
Eric Laurenta1478072015-09-21 17:21:52 -07002713 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002714
Eric Laurent949a0892013-09-20 09:20:13 -07002715 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2716 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002717 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002718 compress_get_tstamp(out->compr, &dsp_frames,
2719 &out->sample_rate);
2720 ALOGVV("%s rendered frames %ld sample_rate %d",
2721 __func__, dsp_frames, out->sample_rate);
2722 *frames = dsp_frames;
2723 ret = 0;
2724 /* this is the best we can do */
2725 clock_gettime(CLOCK_MONOTONIC, timestamp);
2726 }
2727 } else {
2728 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002729 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002730 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2731 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002732 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002733 // This adjustment accounts for buffering after app processor.
2734 // It is based on estimated DSP latency per use case, rather than exact.
2735 signed_frames -=
2736 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2737
Eric Laurent949a0892013-09-20 09:20:13 -07002738 // It would be unusual for this value to be negative, but check just in case ...
2739 if (signed_frames >= 0) {
2740 *frames = signed_frames;
2741 ret = 0;
2742 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002743 }
2744 }
2745 }
2746
2747 pthread_mutex_unlock(&out->lock);
2748
2749 return ret;
2750}
2751
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002752static int out_set_callback(struct audio_stream_out *stream,
2753 stream_callback_t callback, void *cookie)
2754{
2755 struct stream_out *out = (struct stream_out *)stream;
2756
2757 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002758 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002759 out->offload_callback = callback;
2760 out->offload_cookie = cookie;
2761 pthread_mutex_unlock(&out->lock);
2762 return 0;
2763}
2764
2765static int out_pause(struct audio_stream_out* stream)
2766{
2767 struct stream_out *out = (struct stream_out *)stream;
2768 int status = -ENOSYS;
2769 ALOGV("%s", __func__);
2770 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002771 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002772 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2773 status = compress_pause(out->compr);
2774 out->offload_state = OFFLOAD_STATE_PAUSED;
2775 }
2776 pthread_mutex_unlock(&out->lock);
2777 }
2778 return status;
2779}
2780
2781static int out_resume(struct audio_stream_out* stream)
2782{
2783 struct stream_out *out = (struct stream_out *)stream;
2784 int status = -ENOSYS;
2785 ALOGV("%s", __func__);
2786 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2787 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002788 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002789 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2790 status = compress_resume(out->compr);
2791 out->offload_state = OFFLOAD_STATE_PLAYING;
2792 }
2793 pthread_mutex_unlock(&out->lock);
2794 }
2795 return status;
2796}
2797
2798static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2799{
2800 struct stream_out *out = (struct stream_out *)stream;
2801 int status = -ENOSYS;
2802 ALOGV("%s", __func__);
2803 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002804 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002805 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2806 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2807 else
2808 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2809 pthread_mutex_unlock(&out->lock);
2810 }
2811 return status;
2812}
2813
2814static int out_flush(struct audio_stream_out* stream)
2815{
2816 struct stream_out *out = (struct stream_out *)stream;
2817 ALOGV("%s", __func__);
2818 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002819 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002820 stop_compressed_output_l(out);
2821 pthread_mutex_unlock(&out->lock);
2822 return 0;
2823 }
2824 return -ENOSYS;
2825}
2826
Eric Laurent0e46adf2016-12-16 12:49:24 -08002827static int out_stop(const struct audio_stream_out* stream)
2828{
2829 struct stream_out *out = (struct stream_out *)stream;
2830 struct audio_device *adev = out->dev;
2831 int ret = -ENOSYS;
2832
2833 ALOGV("%s", __func__);
2834 pthread_mutex_lock(&adev->lock);
2835 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2836 out->playback_started && out->pcm != NULL) {
2837 pcm_stop(out->pcm);
2838 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002839 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002840 }
2841 pthread_mutex_unlock(&adev->lock);
2842 return ret;
2843}
2844
2845static int out_start(const struct audio_stream_out* stream)
2846{
2847 struct stream_out *out = (struct stream_out *)stream;
2848 struct audio_device *adev = out->dev;
2849 int ret = -ENOSYS;
2850
2851 ALOGV("%s", __func__);
2852 pthread_mutex_lock(&adev->lock);
2853 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2854 !out->playback_started && out->pcm != NULL) {
2855 ret = start_output_stream(out);
2856 if (ret == 0) {
2857 out->playback_started = true;
2858 }
2859 }
2860 pthread_mutex_unlock(&adev->lock);
2861 return ret;
2862}
2863
Phil Burkbc991042017-02-24 08:06:44 -08002864/*
2865 * Modify config->period_count based on min_size_frames
2866 */
2867static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2868{
2869 int periodCountRequested = (min_size_frames + config->period_size - 1)
2870 / config->period_size;
2871 int periodCount = MMAP_PERIOD_COUNT_MIN;
2872
2873 ALOGV("%s original config.period_size = %d config.period_count = %d",
2874 __func__, config->period_size, config->period_count);
2875
2876 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2877 periodCount *= 2;
2878 }
2879 config->period_count = periodCount;
2880
2881 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2882}
2883
Eric Laurent0e46adf2016-12-16 12:49:24 -08002884static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2885 int32_t min_size_frames,
2886 struct audio_mmap_buffer_info *info)
2887{
2888 struct stream_out *out = (struct stream_out *)stream;
2889 struct audio_device *adev = out->dev;
2890 int ret = 0;
2891 unsigned int offset1;
2892 unsigned int frames1;
2893 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002894 uint32_t mmap_size;
2895 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002896
2897 ALOGV("%s", __func__);
2898 pthread_mutex_lock(&adev->lock);
2899
2900 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002901 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002902 ret = -EINVAL;
2903 goto exit;
2904 }
2905 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002906 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002907 ret = -ENOSYS;
2908 goto exit;
2909 }
2910 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2911 if (out->pcm_device_id < 0) {
2912 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2913 __func__, out->pcm_device_id, out->usecase);
2914 ret = -EINVAL;
2915 goto exit;
2916 }
Phil Burkbc991042017-02-24 08:06:44 -08002917
2918 adjust_mmap_period_count(&out->config, min_size_frames);
2919
Eric Laurent0e46adf2016-12-16 12:49:24 -08002920 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2921 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2922 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2923 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2924 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2925 step = "open";
2926 ret = -ENODEV;
2927 goto exit;
2928 }
2929 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2930 if (ret < 0) {
2931 step = "begin";
2932 goto exit;
2933 }
2934 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002935 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002936 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002937 ret = platform_get_mmap_data_fd(adev->platform,
2938 out->pcm_device_id, 0 /*playback*/,
2939 &info->shared_memory_fd,
2940 &mmap_size);
2941 if (ret < 0) {
2942 // Fall back to non exclusive mode
2943 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2944 } else {
2945 if (mmap_size < buffer_size) {
2946 step = "mmap";
2947 goto exit;
2948 }
2949 // FIXME: indicate exclusive mode support by returning a negative buffer size
2950 info->buffer_size_frames *= -1;
2951 }
2952 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002953
2954 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2955 if (ret < 0) {
2956 step = "commit";
2957 goto exit;
2958 }
Phil Burkbc991042017-02-24 08:06:44 -08002959
2960 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002961 ret = 0;
2962
2963 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2964 __func__, info->shared_memory_address, info->buffer_size_frames);
2965
2966exit:
2967 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002968 if (out->pcm == NULL) {
2969 ALOGE("%s: %s - %d", __func__, step, ret);
2970 } else {
2971 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002972 pcm_close(out->pcm);
2973 out->pcm = NULL;
2974 }
2975 }
2976 pthread_mutex_unlock(&adev->lock);
2977 return ret;
2978}
2979
2980static int out_get_mmap_position(const struct audio_stream_out *stream,
2981 struct audio_mmap_position *position)
2982{
2983 struct stream_out *out = (struct stream_out *)stream;
2984 ALOGVV("%s", __func__);
2985 if (position == NULL) {
2986 return -EINVAL;
2987 }
2988 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2989 return -ENOSYS;
2990 }
2991 if (out->pcm == NULL) {
2992 return -ENOSYS;
2993 }
2994
2995 struct timespec ts = { 0, 0 };
2996 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2997 if (ret < 0) {
2998 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2999 return ret;
3000 }
Andy Hungfc044e12017-03-20 09:24:22 -07003001 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003002 return 0;
3003}
3004
3005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006/** audio_stream_in implementation **/
3007static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3008{
3009 struct stream_in *in = (struct stream_in *)stream;
3010
3011 return in->config.rate;
3012}
3013
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003014static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015{
3016 return -ENOSYS;
3017}
3018
3019static size_t in_get_buffer_size(const struct audio_stream *stream)
3020{
3021 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003022 return in->config.period_size * in->af_period_multiplier *
3023 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024}
3025
3026static uint32_t in_get_channels(const struct audio_stream *stream)
3027{
3028 struct stream_in *in = (struct stream_in *)stream;
3029
3030 return in->channel_mask;
3031}
3032
vivek mehta4ed66e62016-04-15 23:33:34 -07003033static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034{
vivek mehta4ed66e62016-04-15 23:33:34 -07003035 struct stream_in *in = (struct stream_in *)stream;
3036 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037}
3038
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003039static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040{
3041 return -ENOSYS;
3042}
3043
3044static int in_standby(struct audio_stream *stream)
3045{
3046 struct stream_in *in = (struct stream_in *)stream;
3047 struct audio_device *adev = in->dev;
3048 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003049 bool do_stop = true;
3050
Eric Laurent994a6932013-07-17 11:51:42 -07003051 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003052
3053 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003054
3055 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003056 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003057 audio_extn_sound_trigger_stop_lab(in);
3058 in->standby = true;
3059 }
3060
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003062 if (adev->adm_deregister_stream)
3063 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3064
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003065 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003067 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003068 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003069 in->capture_started = false;
3070 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003071 if (in->pcm) {
3072 pcm_close(in->pcm);
3073 in->pcm = NULL;
3074 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003075 adev->enable_voicerx = false;
3076 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003077 if (do_stop) {
3078 status = stop_input_stream(in);
3079 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003080 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 }
3082 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003083 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003084 return status;
3085}
3086
Andy Hungd13f0d32017-06-12 13:58:37 -07003087static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088{
Andy Hungd13f0d32017-06-12 13:58:37 -07003089 struct stream_in *in = (struct stream_in *)stream;
3090
3091 // We try to get the lock for consistency,
3092 // but it isn't necessary for these variables.
3093 // If we're not in standby, we may be blocked on a read.
3094 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3095 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3096 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3097 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3098
3099 if (locked) {
3100 pthread_mutex_unlock(&in->lock);
3101 }
3102
3103 // dump error info
3104 (void)error_log_dump(
3105 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 return 0;
3107}
3108
3109static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3110{
3111 struct stream_in *in = (struct stream_in *)stream;
3112 struct audio_device *adev = in->dev;
3113 struct str_parms *parms;
3114 char *str;
3115 char value[32];
3116 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003117 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118
Eric Laurent994a6932013-07-17 11:51:42 -07003119 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120 parms = str_parms_create_str(kvpairs);
3121
3122 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3123
Eric Laurenta1478072015-09-21 17:21:52 -07003124 lock_input_stream(in);
3125
Eric Laurent150dbfe2013-02-27 14:31:02 -08003126 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127 if (ret >= 0) {
3128 val = atoi(value);
3129 /* no audio source uses val == 0 */
3130 if ((in->source != val) && (val != 0)) {
3131 in->source = val;
3132 }
3133 }
3134
3135 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 if (ret >= 0) {
3138 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003139 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003140
3141 // Workaround: If routing to an non existing usb device, fail gracefully
3142 // The routing request will otherwise block during 10 second
3143 if (audio_is_usb_in_device(val) && !audio_extn_usb_alive(adev->snd_card)) {
3144 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d",
3145 adev->snd_card);
3146 status = -ENOSYS;
3147 } else {
3148
3149 in->device = val;
3150 /* If recording is in progress, change the tx device to new device */
3151 if (!in->standby) {
3152 ALOGV("update input routing change");
3153 // inform adm before actual routing to prevent glitches.
3154 if (adev->adm_on_routing_change) {
3155 adev->adm_on_routing_change(adev->adm_data,
3156 in->capture_handle);
3157 }
3158 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003159 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003160 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161 }
3162 }
3163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003165 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166
3167 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003168 ALOGV("%s: exit: status(%d)", __func__, status);
3169 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170}
3171
Haynes Mathew George569b7482017-05-08 14:44:27 -07003172static char* in_get_parameters(const struct audio_stream *stream,
3173 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003175 struct stream_in *in = (struct stream_in *)stream;
3176 struct str_parms *query = str_parms_create_str(keys);
3177 char *str;
3178 struct str_parms *reply = str_parms_create();
3179 bool replied = false;
3180
3181 ALOGV("%s: enter: keys - %s", __func__, keys);
3182 replied |= stream_get_parameter_channels(query, reply,
3183 &in->supported_channel_masks[0]);
3184 replied |= stream_get_parameter_formats(query, reply,
3185 &in->supported_formats[0]);
3186 replied |= stream_get_parameter_rates(query, reply,
3187 &in->supported_sample_rates[0]);
3188 if (replied) {
3189 str = str_parms_to_str(reply);
3190 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003191 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003192 }
3193 str_parms_destroy(query);
3194 str_parms_destroy(reply);
3195 ALOGV("%s: exit: returns - %s", __func__, str);
3196 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197}
3198
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003199static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003201 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202}
3203
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003204static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3205{
3206 if (!stream || !parms)
3207 return;
3208
3209 struct stream_in *in = (struct stream_in *)stream;
3210 struct audio_device *adev = in->dev;
3211
3212 card_status_t status;
3213 int card;
3214 if (parse_snd_card_status(parms, &card, &status) < 0)
3215 return;
3216
3217 pthread_mutex_lock(&adev->lock);
3218 bool valid_cb = (card == adev->snd_card);
3219 pthread_mutex_unlock(&adev->lock);
3220
3221 if (!valid_cb)
3222 return;
3223
3224 lock_input_stream(in);
3225 if (in->card_status != status)
3226 in->card_status = status;
3227 pthread_mutex_unlock(&in->lock);
3228
3229 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3230 use_case_table[in->usecase],
3231 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3232
3233 // a better solution would be to report error back to AF and let
3234 // it put the stream to standby
3235 if (status == CARD_STATUS_OFFLINE)
3236 in_standby(&in->stream.common);
3237
3238 return;
3239}
3240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3242 size_t bytes)
3243{
3244 struct stream_in *in = (struct stream_in *)stream;
3245 struct audio_device *adev = in->dev;
3246 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003247 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003248 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249
Eric Laurenta1478072015-09-21 17:21:52 -07003250 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003251 const size_t frame_size = audio_stream_in_frame_size(stream);
3252 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003253
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003254 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003255 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003256 /* Read from sound trigger HAL */
3257 audio_extn_sound_trigger_read(in, buffer, bytes);
3258 pthread_mutex_unlock(&in->lock);
3259 return bytes;
3260 }
3261
Eric Laurent0e46adf2016-12-16 12:49:24 -08003262 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3263 ret = -ENOSYS;
3264 goto exit;
3265 }
3266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003268 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003270 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272 goto exit;
3273 }
3274 in->standby = 0;
3275 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276
Andy Hungd13f0d32017-06-12 13:58:37 -07003277 // errors that occur here are read errors.
3278 error_code = ERROR_CODE_READ;
3279
Haynes Mathew George03c40102016-01-29 17:57:48 -08003280 //what's the duration requested by the client?
3281 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3282 in->config.rate;
3283 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003284
Haynes Mathew George03c40102016-01-29 17:57:48 -08003285 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003287 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003288 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003289 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003290 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003291 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003292 if (ret < 0) {
3293 ALOGE("Failed to read w/err %s", strerror(errno));
3294 ret = -errno;
3295 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003296 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3297 if (bytes % 4 == 0) {
3298 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3299 int_buf_stream = buffer;
3300 for (size_t itt=0; itt < bytes/4 ; itt++) {
3301 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003302 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003303 } else {
3304 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3305 ret = -EINVAL;
3306 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003307 }
3308 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 }
3310
Haynes Mathew George03c40102016-01-29 17:57:48 -08003311 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313 /*
3314 * Instead of writing zeroes here, we could trust the hardware
3315 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003316 * 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 -08003317 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003318 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003320 in->frames_muted += frames;
3321 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322
3323exit:
3324 pthread_mutex_unlock(&in->lock);
3325
3326 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003327 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328 in_standby(&in->stream.common);
3329 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003330 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003331 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003332 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003333 }
3334 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003335 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336 }
3337 return bytes;
3338}
3339
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003340static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341{
3342 return 0;
3343}
3344
Andy Hung6ebe5962016-01-15 17:46:57 -08003345static int in_get_capture_position(const struct audio_stream_in *stream,
3346 int64_t *frames, int64_t *time)
3347{
3348 if (stream == NULL || frames == NULL || time == NULL) {
3349 return -EINVAL;
3350 }
3351 struct stream_in *in = (struct stream_in *)stream;
3352 int ret = -ENOSYS;
3353
3354 lock_input_stream(in);
3355 if (in->pcm) {
3356 struct timespec timestamp;
3357 unsigned int avail;
3358 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3359 *frames = in->frames_read + avail;
3360 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3361 ret = 0;
3362 }
3363 }
3364 pthread_mutex_unlock(&in->lock);
3365 return ret;
3366}
3367
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003368static int add_remove_audio_effect(const struct audio_stream *stream,
3369 effect_handle_t effect,
3370 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003372 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003373 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003374 int status = 0;
3375 effect_descriptor_t desc;
3376
3377 status = (*effect)->get_descriptor(effect, &desc);
3378 if (status != 0)
3379 return status;
3380
Eric Laurenta1478072015-09-21 17:21:52 -07003381 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003382 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003383 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003384 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003385 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003386 in->enable_aec != enable &&
3387 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3388 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003389 if (!enable)
3390 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003391 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3392 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3393 adev->enable_voicerx = enable;
3394 struct audio_usecase *usecase;
3395 struct listnode *node;
3396 list_for_each(node, &adev->usecase_list) {
3397 usecase = node_to_item(node, struct audio_usecase, list);
3398 if (usecase->type == PCM_PLAYBACK) {
3399 select_devices(adev, usecase->id);
3400 break;
3401 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003402 }
3403 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003404 if (!in->standby)
3405 select_devices(in->dev, in->usecase);
3406 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003407 if (in->enable_ns != enable &&
3408 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3409 in->enable_ns = enable;
3410 if (!in->standby)
3411 select_devices(in->dev, in->usecase);
3412 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003413 pthread_mutex_unlock(&in->dev->lock);
3414 pthread_mutex_unlock(&in->lock);
3415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 return 0;
3417}
3418
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003419static int in_add_audio_effect(const struct audio_stream *stream,
3420 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421{
Eric Laurent994a6932013-07-17 11:51:42 -07003422 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003423 return add_remove_audio_effect(stream, effect, true);
3424}
3425
3426static int in_remove_audio_effect(const struct audio_stream *stream,
3427 effect_handle_t effect)
3428{
Eric Laurent994a6932013-07-17 11:51:42 -07003429 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003430 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431}
3432
Eric Laurent0e46adf2016-12-16 12:49:24 -08003433static int in_stop(const struct audio_stream_in* stream)
3434{
3435 struct stream_in *in = (struct stream_in *)stream;
3436 struct audio_device *adev = in->dev;
3437
3438 int ret = -ENOSYS;
3439 ALOGV("%s", __func__);
3440 pthread_mutex_lock(&adev->lock);
3441 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3442 in->capture_started && in->pcm != NULL) {
3443 pcm_stop(in->pcm);
3444 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003445 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003446 }
3447 pthread_mutex_unlock(&adev->lock);
3448 return ret;
3449}
3450
3451static int in_start(const struct audio_stream_in* stream)
3452{
3453 struct stream_in *in = (struct stream_in *)stream;
3454 struct audio_device *adev = in->dev;
3455 int ret = -ENOSYS;
3456
3457 ALOGV("%s in %p", __func__, in);
3458 pthread_mutex_lock(&adev->lock);
3459 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3460 !in->capture_started && in->pcm != NULL) {
3461 if (!in->capture_started) {
3462 ret = start_input_stream(in);
3463 if (ret == 0) {
3464 in->capture_started = true;
3465 }
3466 }
3467 }
3468 pthread_mutex_unlock(&adev->lock);
3469 return ret;
3470}
3471
3472static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3473 int32_t min_size_frames,
3474 struct audio_mmap_buffer_info *info)
3475{
3476 struct stream_in *in = (struct stream_in *)stream;
3477 struct audio_device *adev = in->dev;
3478 int ret = 0;
3479 unsigned int offset1;
3480 unsigned int frames1;
3481 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003482 uint32_t mmap_size;
3483 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003484
3485 pthread_mutex_lock(&adev->lock);
3486 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003487
Eric Laurent0e46adf2016-12-16 12:49:24 -08003488 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003489 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003490 ret = -EINVAL;
3491 goto exit;
3492 }
3493 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003494 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003495 ALOGV("%s in %p", __func__, in);
3496 ret = -ENOSYS;
3497 goto exit;
3498 }
3499 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3500 if (in->pcm_device_id < 0) {
3501 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3502 __func__, in->pcm_device_id, in->usecase);
3503 ret = -EINVAL;
3504 goto exit;
3505 }
Phil Burkbc991042017-02-24 08:06:44 -08003506
3507 adjust_mmap_period_count(&in->config, min_size_frames);
3508
Eric Laurent0e46adf2016-12-16 12:49:24 -08003509 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3510 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3511 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3512 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3513 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3514 step = "open";
3515 ret = -ENODEV;
3516 goto exit;
3517 }
3518
3519 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3520 if (ret < 0) {
3521 step = "begin";
3522 goto exit;
3523 }
3524 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003525 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003526 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003527 ret = platform_get_mmap_data_fd(adev->platform,
3528 in->pcm_device_id, 1 /*capture*/,
3529 &info->shared_memory_fd,
3530 &mmap_size);
3531 if (ret < 0) {
3532 // Fall back to non exclusive mode
3533 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3534 } else {
3535 if (mmap_size < buffer_size) {
3536 step = "mmap";
3537 goto exit;
3538 }
3539 // FIXME: indicate exclusive mode support by returning a negative buffer size
3540 info->buffer_size_frames *= -1;
3541 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003542
Haynes Mathew George96483a22017-03-28 14:52:47 -07003543 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003544
3545 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3546 if (ret < 0) {
3547 step = "commit";
3548 goto exit;
3549 }
3550
Phil Burkbc991042017-02-24 08:06:44 -08003551 in->standby = false;
3552 ret = 0;
3553
Eric Laurent0e46adf2016-12-16 12:49:24 -08003554 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3555 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003556
3557exit:
3558 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003559 if (in->pcm == NULL) {
3560 ALOGE("%s: %s - %d", __func__, step, ret);
3561 } else {
3562 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003563 pcm_close(in->pcm);
3564 in->pcm = NULL;
3565 }
3566 }
3567 pthread_mutex_unlock(&adev->lock);
3568 return ret;
3569}
3570
3571static int in_get_mmap_position(const struct audio_stream_in *stream,
3572 struct audio_mmap_position *position)
3573{
3574 struct stream_in *in = (struct stream_in *)stream;
3575 ALOGVV("%s", __func__);
3576 if (position == NULL) {
3577 return -EINVAL;
3578 }
3579 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3580 return -ENOSYS;
3581 }
3582 if (in->pcm == NULL) {
3583 return -ENOSYS;
3584 }
3585 struct timespec ts = { 0, 0 };
3586 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3587 if (ret < 0) {
3588 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3589 return ret;
3590 }
Andy Hungfc044e12017-03-20 09:24:22 -07003591 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003592 return 0;
3593}
3594
3595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003596static int adev_open_output_stream(struct audio_hw_device *dev,
3597 audio_io_handle_t handle,
3598 audio_devices_t devices,
3599 audio_output_flags_t flags,
3600 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003601 struct audio_stream_out **stream_out,
3602 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003603{
3604 struct audio_device *adev = (struct audio_device *)dev;
3605 struct stream_out *out;
3606 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003607 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3608 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3609 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3610 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611
Andy Hungd9653bd2017-08-01 19:31:39 -07003612 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3613 return -ENOSYS;
3614 }
3615
Eric Laurent994a6932013-07-17 11:51:42 -07003616 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 __func__, config->sample_rate, config->channel_mask, devices, flags);
3618 *stream_out = NULL;
3619 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3620
3621 if (devices == AUDIO_DEVICE_NONE)
3622 devices = AUDIO_DEVICE_OUT_SPEAKER;
3623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 out->flags = flags;
3625 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003626 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003627 out->format = config->format;
3628 out->sample_rate = config->sample_rate;
3629 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3630 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003631 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632
3633 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003634 if (audio_is_linear_pcm(out->format) &&
3635 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003636 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003637 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003638 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003639 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003640 if (config->sample_rate == 0)
3641 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3642 if (config->channel_mask == 0)
3643 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3644 if (config->format == AUDIO_FORMAT_DEFAULT)
3645 config->format = AUDIO_FORMAT_PCM_16_BIT;
3646 } else if (is_usb_dev) {
3647 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3648 &config->format,
3649 &out->supported_formats[0],
3650 MAX_SUPPORTED_FORMATS,
3651 &config->channel_mask,
3652 &out->supported_channel_masks[0],
3653 MAX_SUPPORTED_CHANNEL_MASKS,
3654 &config->sample_rate,
3655 &out->supported_sample_rates[0],
3656 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003657 ALOGV("plugged dev USB ret %d", ret);
3658 } else {
3659 ret = -1;
3660 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003661 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003662 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003663 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003664
Haynes Mathew George569b7482017-05-08 14:44:27 -07003665 out->channel_mask = config->channel_mask;
3666 out->sample_rate = config->sample_rate;
3667 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003668 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3669 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003670 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003672 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003673 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3674 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003675 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003676 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003677 pthread_mutex_lock(&adev->lock);
3678 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3679 pthread_mutex_unlock(&adev->lock);
3680
3681 // reject offload during card offline to allow
3682 // fallback to s/w paths
3683 if (offline) {
3684 ret = -ENODEV;
3685 goto error_open;
3686 }
3687
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003688 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3689 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3690 ALOGE("%s: Unsupported Offload information", __func__);
3691 ret = -EINVAL;
3692 goto error_open;
3693 }
3694 if (!is_supported_format(config->offload_info.format)) {
3695 ALOGE("%s: Unsupported audio format", __func__);
3696 ret = -EINVAL;
3697 goto error_open;
3698 }
3699
3700 out->compr_config.codec = (struct snd_codec *)
3701 calloc(1, sizeof(struct snd_codec));
3702
3703 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3704 if (config->offload_info.channel_mask)
3705 out->channel_mask = config->offload_info.channel_mask;
3706 else if (config->channel_mask)
3707 out->channel_mask = config->channel_mask;
3708 out->format = config->offload_info.format;
3709 out->sample_rate = config->offload_info.sample_rate;
3710
3711 out->stream.set_callback = out_set_callback;
3712 out->stream.pause = out_pause;
3713 out->stream.resume = out_resume;
3714 out->stream.drain = out_drain;
3715 out->stream.flush = out_flush;
3716
3717 out->compr_config.codec->id =
3718 get_snd_codec_id(config->offload_info.format);
3719 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3720 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003721 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003722 out->compr_config.codec->bit_rate =
3723 config->offload_info.bit_rate;
3724 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003725 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003726 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3727
3728 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3729 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003730
3731 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003732 create_offload_callback_thread(out);
3733 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3734 __func__, config->offload_info.version,
3735 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003736 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003737 switch (config->sample_rate) {
3738 case 8000:
3739 case 16000:
3740 case 48000:
3741 out->sample_rate = config->sample_rate;
3742 break;
3743 default:
3744 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003745 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003746 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003747 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3748 out->config = pcm_config_afe_proxy_playback;
3749 adev->voice_tx_output = out;
David Lin6b00c232017-07-26 00:20:16 -07003750 } else if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3751 AUDIO_OUTPUT_FLAG_VOIP_RX)) {
vivek mehtaa68fea62017-06-08 19:04:02 -07003752 uint32_t buffer_size, frame_size;
3753 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3754 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3755 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3756 out->config = pcm_config_voip;
3757 out->config.format = pcm_format_from_audio_format(config->format);
3758 out->config.rate = config->sample_rate;
3759 out->config.channels =
3760 audio_channel_count_from_out_mask(config->channel_mask);
3761 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3762 config->sample_rate,
3763 config->format,
3764 out->config.channels,
3765 false /*is_low_latency*/);
3766 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3767 out->config.period_size = buffer_size / frame_size;
3768 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3769 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003771 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3772 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3773 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003774 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3775 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3776 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003777 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3778 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003779 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003780 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003781 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3782 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3783 out->config = pcm_config_mmap_playback;
3784 out->stream.start = out_start;
3785 out->stream.stop = out_stop;
3786 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3787 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003788 } else {
3789 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3790 out->config = pcm_config_low_latency;
3791 }
3792 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003793 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003794 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003795 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003797
3798 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3799 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3800 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3801 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3802 __func__, config->sample_rate, config->format, config->channel_mask);
3803 config->sample_rate = out->sample_rate;
3804 config->format = out->format;
3805 config->channel_mask = out->channel_mask;
3806 ret = -EINVAL;
3807 goto error_open;
3808 }
3809
Andy Hung6fcba9c2014-03-18 11:53:32 -07003810 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3811 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003813 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003814 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003815 adev->primary_output = out;
3816 else {
3817 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003818 ret = -EEXIST;
3819 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003820 }
3821 }
3822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003823 /* Check if this usecase is already existing */
3824 pthread_mutex_lock(&adev->lock);
3825 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3826 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003828 ret = -EEXIST;
3829 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003830 }
3831 pthread_mutex_unlock(&adev->lock);
3832
3833 out->stream.common.get_sample_rate = out_get_sample_rate;
3834 out->stream.common.set_sample_rate = out_set_sample_rate;
3835 out->stream.common.get_buffer_size = out_get_buffer_size;
3836 out->stream.common.get_channels = out_get_channels;
3837 out->stream.common.get_format = out_get_format;
3838 out->stream.common.set_format = out_set_format;
3839 out->stream.common.standby = out_standby;
3840 out->stream.common.dump = out_dump;
3841 out->stream.common.set_parameters = out_set_parameters;
3842 out->stream.common.get_parameters = out_get_parameters;
3843 out->stream.common.add_audio_effect = out_add_audio_effect;
3844 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3845 out->stream.get_latency = out_get_latency;
3846 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003847#ifdef NO_AUDIO_OUT
3848 out->stream.write = out_write_for_no_output;
3849#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003850 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003851#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852 out->stream.get_render_position = out_get_render_position;
3853 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003854 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855
Eric Laurent0e46adf2016-12-16 12:49:24 -08003856 if (out->realtime)
3857 out->af_period_multiplier = af_period_multiplier;
3858 else
3859 out->af_period_multiplier = 1;
3860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003862 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003863 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003865 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003866 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003867 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869 config->format = out->stream.common.get_format(&out->stream.common);
3870 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3871 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3872
Andy Hunga452b0a2017-03-15 14:51:15 -07003873 out->error_log = error_log_create(
3874 ERROR_LOG_ENTRIES,
3875 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3876
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003877 /*
3878 By locking output stream before registering, we allow the callback
3879 to update stream's state only after stream's initial state is set to
3880 adev state.
3881 */
3882 lock_output_stream(out);
3883 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3884 pthread_mutex_lock(&adev->lock);
3885 out->card_status = adev->card_status;
3886 pthread_mutex_unlock(&adev->lock);
3887 pthread_mutex_unlock(&out->lock);
3888
vivek mehta4a824772017-06-08 19:05:49 -07003889 stream_app_type_cfg_init(&out->app_type_cfg);
3890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003892
Eric Laurent994a6932013-07-17 11:51:42 -07003893 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003895
3896error_open:
3897 free(out);
3898 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003899 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003900 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901}
3902
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003903static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904 struct audio_stream_out *stream)
3905{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003906 struct stream_out *out = (struct stream_out *)stream;
3907 struct audio_device *adev = out->dev;
3908
Eric Laurent994a6932013-07-17 11:51:42 -07003909 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003910
3911 // must deregister from sndmonitor first to prevent races
3912 // between the callback and close_stream
3913 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003915 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3916 destroy_offload_callback_thread(out);
3917
3918 if (out->compr_config.codec != NULL)
3919 free(out->compr_config.codec);
3920 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003921
3922 if (adev->voice_tx_output == out)
3923 adev->voice_tx_output = NULL;
3924
Andy Hunga452b0a2017-03-15 14:51:15 -07003925 error_log_destroy(out->error_log);
3926 out->error_log = NULL;
3927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003928 pthread_cond_destroy(&out->cond);
3929 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003930 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003931 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932}
3933
3934static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3935{
3936 struct audio_device *adev = (struct audio_device *)dev;
3937 struct str_parms *parms;
3938 char *str;
3939 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003940 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003941 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003942 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943
Joe Onorato188b6222016-03-01 11:02:27 -08003944 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003945
3946 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947
3948 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003949 status = voice_set_parameters(adev, parms);
3950 if (status != 0) {
3951 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952 }
3953
3954 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3955 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003956 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3958 adev->bluetooth_nrec = true;
3959 else
3960 adev->bluetooth_nrec = false;
3961 }
3962
3963 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3964 if (ret >= 0) {
3965 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3966 adev->screen_off = false;
3967 else
3968 adev->screen_off = true;
3969 }
3970
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003971 ret = str_parms_get_int(parms, "rotation", &val);
3972 if (ret >= 0) {
3973 bool reverse_speakers = false;
3974 switch(val) {
3975 // FIXME: note that the code below assumes that the speakers are in the correct placement
3976 // relative to the user when the device is rotated 90deg from its default rotation. This
3977 // assumption is device-specific, not platform-specific like this code.
3978 case 270:
3979 reverse_speakers = true;
3980 break;
3981 case 0:
3982 case 90:
3983 case 180:
3984 break;
3985 default:
3986 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003987 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003988 }
Eric Laurent03f09432014-03-25 18:09:11 -07003989 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07003990 // check and set swap
3991 // - check if orientation changed and speaker active
3992 // - set rotation and cache the rotation value
3993 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003994 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003995 }
3996
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003997 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3998 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003999 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004000 }
4001
David Linee3fe402017-03-13 10:00:42 -07004002 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4003 if (ret >= 0) {
4004 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004005 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004006 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4007 if (ret >= 0) {
4008 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004009 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004010 }
Eric Laurent99dab492017-06-17 15:19:08 -07004011 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004012 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4013 if (ret >= 0) {
4014 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004015 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004016 }
4017 }
4018 }
4019
4020 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4021 if (ret >= 0) {
4022 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004023 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004024 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4025 if (ret >= 0) {
4026 const int card = atoi(value);
4027
Eric Laurent99dab492017-06-17 15:19:08 -07004028 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004029 }
Eric Laurent99dab492017-06-17 15:19:08 -07004030 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004031 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4032 if (ret >= 0) {
4033 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004034 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004035 }
4036 }
4037 }
4038
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004039 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004040done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004042 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004043 ALOGV("%s: exit with code(%d)", __func__, status);
4044 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045}
4046
4047static char* adev_get_parameters(const struct audio_hw_device *dev,
4048 const char *keys)
4049{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004050 struct audio_device *adev = (struct audio_device *)dev;
4051 struct str_parms *reply = str_parms_create();
4052 struct str_parms *query = str_parms_create_str(keys);
4053 char *str;
4054
4055 pthread_mutex_lock(&adev->lock);
4056
4057 voice_get_parameters(adev, query, reply);
4058 str = str_parms_to_str(reply);
4059 str_parms_destroy(query);
4060 str_parms_destroy(reply);
4061
4062 pthread_mutex_unlock(&adev->lock);
4063 ALOGV("%s: exit: returns - %s", __func__, str);
4064 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065}
4066
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004067static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068{
4069 return 0;
4070}
4071
Haynes Mathew George5191a852013-09-11 14:19:36 -07004072static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4073{
4074 int ret;
4075 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004076
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004077 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4078
Haynes Mathew George5191a852013-09-11 14:19:36 -07004079 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004080 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004081 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004082
Haynes Mathew George5191a852013-09-11 14:19:36 -07004083 return ret;
4084}
4085
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004086static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087{
4088 return -ENOSYS;
4089}
4090
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004091static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4092 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093{
4094 return -ENOSYS;
4095}
4096
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004097static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004098{
4099 return -ENOSYS;
4100}
4101
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004102static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103{
4104 return -ENOSYS;
4105}
4106
4107static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4108{
4109 struct audio_device *adev = (struct audio_device *)dev;
4110
4111 pthread_mutex_lock(&adev->lock);
4112 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004113 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004115 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4116 voice_is_in_call(adev)) {
4117 voice_stop_call(adev);
4118 adev->current_call_output = NULL;
4119 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004120 }
4121 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004122
4123 audio_extn_extspk_set_mode(adev->extspk, mode);
4124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125 return 0;
4126}
4127
4128static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4129{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004130 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004131 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132
Eric Laurent2bafff12016-03-17 12:17:23 -07004133 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004134 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004135 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4136 ret = audio_extn_hfp_set_mic_mute(adev, state);
4137 } else {
4138 ret = voice_set_mic_mute(adev, state);
4139 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004140 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004141 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004142
4143 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144}
4145
4146static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4147{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004148 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004149 return 0;
4150}
4151
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004152static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004153 const struct audio_config *config)
4154{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004155 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156
Eric Laurent74b55762017-07-09 17:04:53 -07004157 /* Don't know if USB HIFI in this context so use true to be conservative */
4158 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4159 true /*is_usb_hifi */) != 0)
4160 return 0;
4161
vivek mehtaa68fea62017-06-08 19:04:02 -07004162 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4163 config->sample_rate, config->format,
4164 channel_count,
4165 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166}
4167
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004168static bool adev_input_allow_hifi_record(struct audio_device *adev,
4169 audio_devices_t devices,
4170 audio_input_flags_t flags,
4171 audio_source_t source) {
4172 const bool allowed = true;
4173
4174 if (!audio_is_usb_in_device(devices))
4175 return !allowed;
4176
4177 switch (flags) {
4178 case AUDIO_INPUT_FLAG_NONE:
4179 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4180 break;
4181 default:
4182 return !allowed;
4183 }
4184
4185 switch (source) {
4186 case AUDIO_SOURCE_DEFAULT:
4187 case AUDIO_SOURCE_MIC:
4188 case AUDIO_SOURCE_UNPROCESSED:
4189 break;
4190 default:
4191 return !allowed;
4192 }
4193
4194 switch (adev->mode) {
4195 case 0:
4196 break;
4197 default:
4198 return !allowed;
4199 }
4200
4201 return allowed;
4202}
4203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004205 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206 audio_devices_t devices,
4207 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004208 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004209 audio_input_flags_t flags,
4210 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004211 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212{
4213 struct audio_device *adev = (struct audio_device *)dev;
4214 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004215 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004216 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004217 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004218 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004219 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4220 devices,
4221 flags,
4222 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004223 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004224 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004225
Andy Hungd9653bd2017-08-01 19:31:39 -07004226 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4227 return -ENOSYS;
4228 }
4229
Eric Laurent74b55762017-07-09 17:04:53 -07004230 if (!(is_usb_dev && may_use_hifi_record)) {
4231 if (config->sample_rate == 0)
4232 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4233 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4234 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4235 if (config->format == AUDIO_FORMAT_DEFAULT)
4236 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004237
Eric Laurent74b55762017-07-09 17:04:53 -07004238 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4239
4240 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4241 return -EINVAL;
4242 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004243
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004244 if (audio_extn_tfa_98xx_is_supported() &&
4245 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004246 return -EINVAL;
4247
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004248 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4249
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004250 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004251 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004252
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253 in->stream.common.get_sample_rate = in_get_sample_rate;
4254 in->stream.common.set_sample_rate = in_set_sample_rate;
4255 in->stream.common.get_buffer_size = in_get_buffer_size;
4256 in->stream.common.get_channels = in_get_channels;
4257 in->stream.common.get_format = in_get_format;
4258 in->stream.common.set_format = in_set_format;
4259 in->stream.common.standby = in_standby;
4260 in->stream.common.dump = in_dump;
4261 in->stream.common.set_parameters = in_set_parameters;
4262 in->stream.common.get_parameters = in_get_parameters;
4263 in->stream.common.add_audio_effect = in_add_audio_effect;
4264 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4265 in->stream.set_gain = in_set_gain;
4266 in->stream.read = in_read;
4267 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004268 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004269
4270 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004271 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004272 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004273 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004274 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004275 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276
Haynes Mathew George569b7482017-05-08 14:44:27 -07004277 if (is_usb_dev && may_use_hifi_record) {
4278 /* HiFi record selects an appropriate format, channel, rate combo
4279 depending on sink capabilities*/
4280 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4281 &config->format,
4282 &in->supported_formats[0],
4283 MAX_SUPPORTED_FORMATS,
4284 &config->channel_mask,
4285 &in->supported_channel_masks[0],
4286 MAX_SUPPORTED_CHANNEL_MASKS,
4287 &config->sample_rate,
4288 &in->supported_sample_rates[0],
4289 MAX_SUPPORTED_SAMPLE_RATES);
4290 if (ret != 0) {
4291 ret = -EINVAL;
4292 goto err_open;
4293 }
Eric Laurent74b55762017-07-09 17:04:53 -07004294 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004295 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004296 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004297 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4298 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4299 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4300 bool ret_error = false;
4301 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4302 from HAL is 8_24
4303 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4304 8_24 return error indicating supported format is 8_24
4305 *> In case of any other source requesting 24 bit or float return error
4306 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004307
vivek mehta57ff9b52016-04-28 14:13:08 -07004308 on error flinger will retry with supported format passed
4309 */
4310 if (source != AUDIO_SOURCE_UNPROCESSED) {
4311 config->format = AUDIO_FORMAT_PCM_16_BIT;
4312 ret_error = true;
4313 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4314 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4315 ret_error = true;
4316 }
4317
4318 if (ret_error) {
4319 ret = -EINVAL;
4320 goto err_open;
4321 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004322 }
4323
vivek mehta57ff9b52016-04-28 14:13:08 -07004324 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004325 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004328 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4329 if (config->sample_rate == 0)
4330 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4331 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4332 config->sample_rate != 8000) {
4333 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4334 ret = -EINVAL;
4335 goto err_open;
4336 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004337
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004338 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4339 config->format = AUDIO_FORMAT_PCM_16_BIT;
4340 ret = -EINVAL;
4341 goto err_open;
4342 }
4343
4344 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4345 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004346 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004347 } else if (is_usb_dev && may_use_hifi_record) {
4348 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4349 in->config = pcm_config_audio_capture;
4350 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004351 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4352 config->sample_rate,
4353 config->format,
4354 channel_count,
4355 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004356 in->config.period_size = buffer_size / frame_size;
4357 in->config.rate = config->sample_rate;
4358 in->af_period_multiplier = 1;
4359 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004360 } else {
4361 in->usecase = USECASE_AUDIO_RECORD;
4362 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004363 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004364 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004365#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004366 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004367#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004368 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004369 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004370 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004371 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004372 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4373 config->sample_rate,
4374 config->format,
4375 channel_count,
4376 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004377 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004378 in->config.rate = config->sample_rate;
4379 in->af_period_multiplier = 1;
4380 } else {
4381 // period size is left untouched for rt mode playback
4382 in->config = pcm_config_audio_capture_rt;
4383 in->af_period_multiplier = af_period_multiplier;
4384 }
4385 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4386 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004387 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004388 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4389 in->config = pcm_config_mmap_capture;
4390 in->stream.start = in_start;
4391 in->stream.stop = in_stop;
4392 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4393 in->stream.get_mmap_position = in_get_mmap_position;
4394 in->af_period_multiplier = 1;
4395 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004396 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004397 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004398 (config->sample_rate == 8000 ||
4399 config->sample_rate == 16000 ||
4400 config->sample_rate == 32000 ||
4401 config->sample_rate == 48000) &&
4402 channel_count == 1) {
4403 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4404 in->config = pcm_config_audio_capture;
4405 frame_size = audio_stream_in_frame_size(&in->stream);
4406 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4407 config->sample_rate,
4408 config->format,
4409 channel_count, false /*is_low_latency*/);
4410 in->config.period_size = buffer_size / frame_size;
4411 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4412 in->config.rate = config->sample_rate;
4413 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004414 } else {
4415 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004416 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004417 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4418 config->sample_rate,
4419 config->format,
4420 channel_count,
4421 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004422 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004423 in->config.rate = config->sample_rate;
4424 in->af_period_multiplier = 1;
4425 }
4426 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4427 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004428 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004429
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004431 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432
Andy Hungd13f0d32017-06-12 13:58:37 -07004433 in->error_log = error_log_create(
4434 ERROR_LOG_ENTRIES,
4435 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4436
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004437 /* This stream could be for sound trigger lab,
4438 get sound trigger pcm if present */
4439 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004440
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004441 lock_input_stream(in);
4442 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4443 pthread_mutex_lock(&adev->lock);
4444 in->card_status = adev->card_status;
4445 pthread_mutex_unlock(&adev->lock);
4446 pthread_mutex_unlock(&in->lock);
4447
vivek mehta4a824772017-06-08 19:05:49 -07004448 stream_app_type_cfg_init(&in->app_type_cfg);
4449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004450 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004451 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004452 return 0;
4453
4454err_open:
4455 free(in);
4456 *stream_in = NULL;
4457 return ret;
4458}
4459
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004460static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004461 struct audio_stream_in *stream)
4462{
Andy Hungd13f0d32017-06-12 13:58:37 -07004463 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004464 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004465
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004466 // must deregister from sndmonitor first to prevent races
4467 // between the callback and close_stream
4468 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004470
4471 error_log_destroy(in->error_log);
4472 in->error_log = NULL;
4473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474 free(stream);
4475
4476 return;
4477}
4478
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004479static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480{
4481 return 0;
4482}
4483
Andy Hung31aca912014-03-20 17:14:59 -07004484/* verifies input and output devices and their capabilities.
4485 *
4486 * This verification is required when enabling extended bit-depth or
4487 * sampling rates, as not all qcom products support it.
4488 *
4489 * Suitable for calling only on initialization such as adev_open().
4490 * It fills the audio_device use_case_table[] array.
4491 *
4492 * Has a side-effect that it needs to configure audio routing / devices
4493 * in order to power up the devices and read the device parameters.
4494 * It does not acquire any hw device lock. Should restore the devices
4495 * back to "normal state" upon completion.
4496 */
4497static int adev_verify_devices(struct audio_device *adev)
4498{
4499 /* enumeration is a bit difficult because one really wants to pull
4500 * the use_case, device id, etc from the hidden pcm_device_table[].
4501 * In this case there are the following use cases and device ids.
4502 *
4503 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4504 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004505 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004506 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4507 * [USECASE_AUDIO_RECORD] = {0, 0},
4508 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4509 * [USECASE_VOICE_CALL] = {2, 2},
4510 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004511 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004512 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4513 */
4514
4515 /* should be the usecases enabled in adev_open_input_stream() */
4516 static const int test_in_usecases[] = {
4517 USECASE_AUDIO_RECORD,
4518 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4519 };
4520 /* should be the usecases enabled in adev_open_output_stream()*/
4521 static const int test_out_usecases[] = {
4522 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4523 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4524 };
4525 static const usecase_type_t usecase_type_by_dir[] = {
4526 PCM_PLAYBACK,
4527 PCM_CAPTURE,
4528 };
4529 static const unsigned flags_by_dir[] = {
4530 PCM_OUT,
4531 PCM_IN,
4532 };
4533
4534 size_t i;
4535 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004536 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004537 char info[512]; /* for possible debug info */
4538
4539 for (dir = 0; dir < 2; ++dir) {
4540 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4541 const unsigned flags_dir = flags_by_dir[dir];
4542 const size_t testsize =
4543 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4544 const int *testcases =
4545 dir ? test_in_usecases : test_out_usecases;
4546 const audio_devices_t audio_device =
4547 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4548
4549 for (i = 0; i < testsize; ++i) {
4550 const audio_usecase_t audio_usecase = testcases[i];
4551 int device_id;
4552 snd_device_t snd_device;
4553 struct pcm_params **pparams;
4554 struct stream_out out;
4555 struct stream_in in;
4556 struct audio_usecase uc_info;
4557 int retval;
4558
4559 pparams = &adev->use_case_table[audio_usecase];
4560 pcm_params_free(*pparams); /* can accept null input */
4561 *pparams = NULL;
4562
4563 /* find the device ID for the use case (signed, for error) */
4564 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4565 if (device_id < 0)
4566 continue;
4567
4568 /* prepare structures for device probing */
4569 memset(&uc_info, 0, sizeof(uc_info));
4570 uc_info.id = audio_usecase;
4571 uc_info.type = usecase_type;
4572 if (dir) {
4573 adev->active_input = &in;
4574 memset(&in, 0, sizeof(in));
4575 in.device = audio_device;
4576 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4577 uc_info.stream.in = &in;
4578 } else {
4579 adev->active_input = NULL;
4580 }
4581 memset(&out, 0, sizeof(out));
4582 out.devices = audio_device; /* only field needed in select_devices */
4583 uc_info.stream.out = &out;
4584 uc_info.devices = audio_device;
4585 uc_info.in_snd_device = SND_DEVICE_NONE;
4586 uc_info.out_snd_device = SND_DEVICE_NONE;
4587 list_add_tail(&adev->usecase_list, &uc_info.list);
4588
4589 /* select device - similar to start_(in/out)put_stream() */
4590 retval = select_devices(adev, audio_usecase);
4591 if (retval >= 0) {
4592 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4593#if LOG_NDEBUG == 0
4594 if (*pparams) {
4595 ALOGV("%s: (%s) card %d device %d", __func__,
4596 dir ? "input" : "output", card_id, device_id);
4597 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004598 } else {
4599 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4600 }
4601#endif
4602 }
4603
4604 /* deselect device - similar to stop_(in/out)put_stream() */
4605 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004606 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004607 /* 2. Disable the rx device */
4608 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004609 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004610 list_remove(&uc_info.list);
4611 }
4612 }
4613 adev->active_input = NULL; /* restore adev state */
4614 return 0;
4615}
4616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617static int adev_close(hw_device_t *device)
4618{
Andy Hung31aca912014-03-20 17:14:59 -07004619 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004621
4622 if (!adev)
4623 return 0;
4624
4625 pthread_mutex_lock(&adev_init_lock);
4626
4627 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004628 audio_extn_snd_mon_unregister_listener(adev);
4629 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004630 audio_route_free(adev->audio_route);
4631 free(adev->snd_dev_ref_cnt);
4632 platform_deinit(adev->platform);
4633 audio_extn_extspk_deinit(adev->extspk);
4634 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004635 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004636 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4637 pcm_params_free(adev->use_case_table[i]);
4638 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004639 if (adev->adm_deinit)
4640 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004641 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004642 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004643
4644 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646 return 0;
4647}
4648
Glenn Kasten4f993392014-05-14 07:30:48 -07004649/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4650 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4651 * just that it _might_ work.
4652 */
4653static int period_size_is_plausible_for_low_latency(int period_size)
4654{
4655 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004656 case 48:
4657 case 96:
4658 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004659 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004660 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004661 case 240:
4662 case 320:
4663 case 480:
4664 return 1;
4665 default:
4666 return 0;
4667 }
4668}
4669
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004670static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4671{
4672 int card;
4673 card_status_t status;
4674
4675 if (!parms)
4676 return;
4677
4678 if (parse_snd_card_status(parms, &card, &status) < 0)
4679 return;
4680
4681 pthread_mutex_lock(&adev->lock);
4682 bool valid_cb = (card == adev->snd_card);
4683 if (valid_cb) {
4684 if (adev->card_status != status) {
4685 adev->card_status = status;
4686 platform_snd_card_update(adev->platform, status);
4687 }
4688 }
4689 pthread_mutex_unlock(&adev->lock);
4690 return;
4691}
4692
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693static int adev_open(const hw_module_t *module, const char *name,
4694 hw_device_t **device)
4695{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004696 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004697
Eric Laurent2bafff12016-03-17 12:17:23 -07004698 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004699 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004700 pthread_mutex_lock(&adev_init_lock);
4701 if (audio_device_ref_count != 0) {
4702 *device = &adev->device.common;
4703 audio_device_ref_count++;
4704 ALOGV("%s: returning existing instance of adev", __func__);
4705 ALOGV("%s: exit", __func__);
4706 pthread_mutex_unlock(&adev_init_lock);
4707 return 0;
4708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004709 adev = calloc(1, sizeof(struct audio_device));
4710
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004711 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004713 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4714 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4715 adev->device.common.module = (struct hw_module_t *)module;
4716 adev->device.common.close = adev_close;
4717
4718 adev->device.init_check = adev_init_check;
4719 adev->device.set_voice_volume = adev_set_voice_volume;
4720 adev->device.set_master_volume = adev_set_master_volume;
4721 adev->device.get_master_volume = adev_get_master_volume;
4722 adev->device.set_master_mute = adev_set_master_mute;
4723 adev->device.get_master_mute = adev_get_master_mute;
4724 adev->device.set_mode = adev_set_mode;
4725 adev->device.set_mic_mute = adev_set_mic_mute;
4726 adev->device.get_mic_mute = adev_get_mic_mute;
4727 adev->device.set_parameters = adev_set_parameters;
4728 adev->device.get_parameters = adev_get_parameters;
4729 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4730 adev->device.open_output_stream = adev_open_output_stream;
4731 adev->device.close_output_stream = adev_close_output_stream;
4732 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004733
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004734 adev->device.close_input_stream = adev_close_input_stream;
4735 adev->device.dump = adev_dump;
4736
4737 /* Set the default route before the PCM stream is opened */
4738 pthread_mutex_lock(&adev->lock);
4739 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004740 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004741 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004742 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004743 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004744 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004745 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004746 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004747 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004748 pthread_mutex_unlock(&adev->lock);
4749
4750 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004751 adev->platform = platform_init(adev);
4752 if (!adev->platform) {
4753 free(adev->snd_dev_ref_cnt);
4754 free(adev);
4755 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4756 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004757 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004758 return -EINVAL;
4759 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004760 adev->extspk = audio_extn_extspk_init(adev);
4761
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004762 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4763 if (adev->visualizer_lib == NULL) {
4764 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4765 } else {
4766 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4767 adev->visualizer_start_output =
4768 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4769 "visualizer_hal_start_output");
4770 adev->visualizer_stop_output =
4771 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4772 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004773 }
4774
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004775 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4776 if (adev->offload_effects_lib == NULL) {
4777 ALOGW("%s: DLOPEN failed for %s", __func__,
4778 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4779 } else {
4780 ALOGV("%s: DLOPEN successful for %s", __func__,
4781 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4782 adev->offload_effects_start_output =
4783 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4784 "offload_effects_bundle_hal_start_output");
4785 adev->offload_effects_stop_output =
4786 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4787 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004788 }
4789
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004790 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4791 if (adev->adm_lib == NULL) {
4792 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4793 } else {
4794 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4795 adev->adm_init = (adm_init_t)
4796 dlsym(adev->adm_lib, "adm_init");
4797 adev->adm_deinit = (adm_deinit_t)
4798 dlsym(adev->adm_lib, "adm_deinit");
4799 adev->adm_register_input_stream = (adm_register_input_stream_t)
4800 dlsym(adev->adm_lib, "adm_register_input_stream");
4801 adev->adm_register_output_stream = (adm_register_output_stream_t)
4802 dlsym(adev->adm_lib, "adm_register_output_stream");
4803 adev->adm_deregister_stream = (adm_deregister_stream_t)
4804 dlsym(adev->adm_lib, "adm_deregister_stream");
4805 adev->adm_request_focus = (adm_request_focus_t)
4806 dlsym(adev->adm_lib, "adm_request_focus");
4807 adev->adm_abandon_focus = (adm_abandon_focus_t)
4808 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004809 adev->adm_set_config = (adm_set_config_t)
4810 dlsym(adev->adm_lib, "adm_set_config");
4811 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4812 dlsym(adev->adm_lib, "adm_request_focus_v2");
4813 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4814 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4815 adev->adm_on_routing_change = (adm_on_routing_change_t)
4816 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004817 }
4818
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004819 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004820 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004822 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004823
Andy Hung31aca912014-03-20 17:14:59 -07004824 if (k_enable_extended_precision)
4825 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004826
Glenn Kasten4f993392014-05-14 07:30:48 -07004827 char value[PROPERTY_VALUE_MAX];
4828 int trial;
4829 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4830 trial = atoi(value);
4831 if (period_size_is_plausible_for_low_latency(trial)) {
4832 pcm_config_low_latency.period_size = trial;
4833 pcm_config_low_latency.start_threshold = trial / 4;
4834 pcm_config_low_latency.avail_min = trial / 4;
4835 configured_low_latency_capture_period_size = trial;
4836 }
4837 }
4838 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4839 trial = atoi(value);
4840 if (period_size_is_plausible_for_low_latency(trial)) {
4841 configured_low_latency_capture_period_size = trial;
4842 }
4843 }
4844
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004845 // commented as full set of app type cfg is sent from platform
4846 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004847 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004848
4849 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4850 af_period_multiplier = atoi(value);
4851 if (af_period_multiplier < 0) {
4852 af_period_multiplier = 2;
4853 } else if (af_period_multiplier > 4) {
4854 af_period_multiplier = 4;
4855 }
4856 ALOGV("new period_multiplier = %d", af_period_multiplier);
4857 }
4858
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004859 audio_extn_tfa_98xx_init(adev);
4860
vivek mehta1a9b7c02015-06-25 11:49:38 -07004861 pthread_mutex_unlock(&adev_init_lock);
4862
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004863 if (adev->adm_init)
4864 adev->adm_data = adev->adm_init();
4865
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004866 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004867 audio_extn_snd_mon_init();
4868 pthread_mutex_lock(&adev->lock);
4869 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4870 adev->card_status = CARD_STATUS_ONLINE;
4871 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004872 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004873
Eric Laurent2bafff12016-03-17 12:17:23 -07004874 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004875 return 0;
4876}
4877
4878static struct hw_module_methods_t hal_module_methods = {
4879 .open = adev_open,
4880};
4881
4882struct audio_module HAL_MODULE_INFO_SYM = {
4883 .common = {
4884 .tag = HARDWARE_MODULE_TAG,
4885 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4886 .hal_api_version = HARDWARE_HAL_API_VERSION,
4887 .id = AUDIO_HARDWARE_MODULE_ID,
4888 .name = "QCOM Audio HAL",
4889 .author = "Code Aurora Forum",
4890 .methods = &hal_module_methods,
4891 },
4892};