blob: be472b3785c5a3ffd4b06bb8afece88788b86dce [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
52#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070076#define PROXY_OPEN_RETRY_COUNT 100
77#define PROXY_OPEN_WAIT_TIME 20
78
vivek mehtadae44712015-07-27 14:13:18 -070079#define MIN_CHANNEL_COUNT 1
80#define DEFAULT_CHANNEL_COUNT 2
81
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
83#define MAX_CHANNEL_COUNT 1
84#else
vivek mehtadae44712015-07-27 14:13:18 -070085#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
86#define XSTR(x) STR(x)
87#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#endif
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),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700303 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
304 //TBD - string values for channel_in > 2?
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800305};
306
Haynes Mathew George5191a852013-09-11 14:19:36 -0700307static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700308static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700309static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700310static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700311//cache last MBDRC cal step level
312static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700313
Andy Hung9e737de2017-05-22 10:51:22 -0700314// TODO: Consider moving this to a pthread_once() if we have more
315// static initialization required.
316static bool is_userdebug_or_eng_build() {
317 char value[PROPERTY_VALUE_MAX];
318 (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
319 return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
320}
321
Haynes Mathew George03c40102016-01-29 17:57:48 -0800322static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
323 int flags __unused)
324{
325 int dir = 0;
326 switch (uc_id) {
327 case USECASE_AUDIO_RECORD_LOW_LATENCY:
328 dir = 1;
329 case USECASE_AUDIO_PLAYBACK_ULL:
330 break;
331 default:
332 return false;
333 }
334
335 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
336 PCM_PLAYBACK : PCM_CAPTURE);
337 if (adev->adm_is_noirq_avail)
338 return adev->adm_is_noirq_avail(adev->adm_data,
339 adev->snd_card, dev_id, dir);
340 return false;
341}
342
343static void register_out_stream(struct stream_out *out)
344{
345 struct audio_device *adev = out->dev;
346 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
347 return;
348
349 if (!adev->adm_register_output_stream)
350 return;
351
352 adev->adm_register_output_stream(adev->adm_data,
353 out->handle,
354 out->flags);
355
356 if (!adev->adm_set_config)
357 return;
358
359 if (out->realtime) {
360 adev->adm_set_config(adev->adm_data,
361 out->handle,
362 out->pcm, &out->config);
363 }
364}
365
366static void register_in_stream(struct stream_in *in)
367{
368 struct audio_device *adev = in->dev;
369 if (!adev->adm_register_input_stream)
370 return;
371
372 adev->adm_register_input_stream(adev->adm_data,
373 in->capture_handle,
374 in->flags);
375
376 if (!adev->adm_set_config)
377 return;
378
379 if (in->realtime) {
380 adev->adm_set_config(adev->adm_data,
381 in->capture_handle,
382 in->pcm,
383 &in->config);
384 }
385}
386
387static void request_out_focus(struct stream_out *out, long ns)
388{
389 struct audio_device *adev = out->dev;
390
Haynes Mathew George03c40102016-01-29 17:57:48 -0800391 if (adev->adm_request_focus_v2) {
392 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
393 } else if (adev->adm_request_focus) {
394 adev->adm_request_focus(adev->adm_data, out->handle);
395 }
396}
397
398static void request_in_focus(struct stream_in *in, long ns)
399{
400 struct audio_device *adev = in->dev;
401
Haynes Mathew George03c40102016-01-29 17:57:48 -0800402 if (adev->adm_request_focus_v2) {
403 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
404 } else if (adev->adm_request_focus) {
405 adev->adm_request_focus(adev->adm_data, in->capture_handle);
406 }
407}
408
409static void release_out_focus(struct stream_out *out, long ns __unused)
410{
411 struct audio_device *adev = out->dev;
412
413 if (adev->adm_abandon_focus)
414 adev->adm_abandon_focus(adev->adm_data, out->handle);
415}
416
417static void release_in_focus(struct stream_in *in, long ns __unused)
418{
419 struct audio_device *adev = in->dev;
420 if (adev->adm_abandon_focus)
421 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
422}
423
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700424static int parse_snd_card_status(struct str_parms * parms, int * card,
425 card_status_t * status)
426{
427 char value[32]={0};
428 char state[32]={0};
429
430 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
431
432 if (ret < 0)
433 return -1;
434
435 // sscanf should be okay as value is of max length 32.
436 // same as sizeof state.
437 if (sscanf(value, "%d,%s", card, state) < 2)
438 return -1;
439
440 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
441 CARD_STATUS_OFFLINE;
442 return 0;
443}
444
vivek mehta1a9b7c02015-06-25 11:49:38 -0700445__attribute__ ((visibility ("default")))
446bool audio_hw_send_gain_dep_calibration(int level) {
447 bool ret_val = false;
448 ALOGV("%s: enter ... ", __func__);
449
450 pthread_mutex_lock(&adev_init_lock);
451
452 if (adev != NULL && adev->platform != NULL) {
453 pthread_mutex_lock(&adev->lock);
454 ret_val = platform_send_gain_dep_cal(adev->platform, level);
455 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700456
457 // if cal set fails, cache level info
458 // if cal set succeds, reset known last cal set
459 if (!ret_val)
460 last_known_cal_step = level;
461 else if (last_known_cal_step != -1)
462 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700463 } else {
464 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
465 }
466
467 pthread_mutex_unlock(&adev_init_lock);
468
469 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
470 return ret_val;
471}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700472
vivek mehtaa8d7c922016-05-25 14:40:44 -0700473__attribute__ ((visibility ("default")))
474int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
475 int table_size) {
476 int ret_val = 0;
477 ALOGV("%s: enter ... ", __func__);
478
479 pthread_mutex_lock(&adev_init_lock);
480 if (adev == NULL) {
481 ALOGW("%s: adev is NULL .... ", __func__);
482 goto done;
483 }
484
485 pthread_mutex_lock(&adev->lock);
486 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
487 pthread_mutex_unlock(&adev->lock);
488done:
489 pthread_mutex_unlock(&adev_init_lock);
490 ALOGV("%s: exit ... ", __func__);
491 return ret_val;
492}
493
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700494static bool is_supported_format(audio_format_t format)
495{
Eric Laurent8251ac82014-07-23 11:00:25 -0700496 switch (format) {
497 case AUDIO_FORMAT_MP3:
498 case AUDIO_FORMAT_AAC_LC:
499 case AUDIO_FORMAT_AAC_HE_V1:
500 case AUDIO_FORMAT_AAC_HE_V2:
501 return true;
502 default:
503 break;
504 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700505 return false;
506}
507
Haynes Mathew George03c40102016-01-29 17:57:48 -0800508static inline bool is_mmap_usecase(audio_usecase_t uc_id)
509{
510 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
511 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
512}
513
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700514static int get_snd_codec_id(audio_format_t format)
515{
516 int id = 0;
517
Eric Laurent8251ac82014-07-23 11:00:25 -0700518 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700519 case AUDIO_FORMAT_MP3:
520 id = SND_AUDIOCODEC_MP3;
521 break;
522 case AUDIO_FORMAT_AAC:
523 id = SND_AUDIOCODEC_AAC;
524 break;
525 default:
526 ALOGE("%s: Unsupported audio format", __func__);
527 }
528
529 return id;
530}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800531
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800532static int audio_ssr_status(struct audio_device *adev)
533{
534 int ret = 0;
535 struct mixer_ctl *ctl;
536 const char *mixer_ctl_name = "Audio SSR Status";
537
538 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
539 ret = mixer_ctl_get_value(ctl, 0);
540 ALOGD("%s: value: %d", __func__, ret);
541 return ret;
542}
543
vivek mehta4a824772017-06-08 19:05:49 -0700544static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
545{
546 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
547}
548
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800549int enable_audio_route(struct audio_device *adev,
550 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800551{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700552 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800553 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800554
555 if (usecase == NULL)
556 return -EINVAL;
557
558 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
559
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800560 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700561 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800562 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800564
Yamit Mehtae3b99562016-09-16 22:44:00 +0530565 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800566 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800567 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500568 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700569 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700570 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800572 ALOGV("%s: exit", __func__);
573 return 0;
574}
575
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800576int disable_audio_route(struct audio_device *adev,
577 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800578{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800580 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800581
582 if (usecase == NULL)
583 return -EINVAL;
584
585 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700586 if (usecase->type == PCM_CAPTURE)
587 snd_device = usecase->in_snd_device;
588 else
589 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800590 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500591 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700592 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700593 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800594
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800595 ALOGV("%s: exit", __func__);
596 return 0;
597}
598
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800599int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700600 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800601{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700602 int i, num_devices = 0;
603 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800604 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800605 if (snd_device < SND_DEVICE_MIN ||
606 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800607 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800608 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800609 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700610
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700611 platform_send_audio_calibration(adev->platform, snd_device);
612
vivek mehtade4849c2016-03-03 17:23:38 -0800613 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700614 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700615 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800616 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700617 }
618
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700619 /* due to the possibility of calibration overwrite between listen
620 and audio, notify sound trigger hal before audio calibration is sent */
621 audio_extn_sound_trigger_update_device_status(snd_device,
622 ST_EVENT_SND_DEVICE_BUSY);
623
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700624 if (audio_extn_spkr_prot_is_enabled())
625 audio_extn_spkr_prot_calib_cancel(adev);
626
zhaoyang yin4211fad2015-06-04 21:13:25 +0800627 audio_extn_dsm_feedback_enable(adev, snd_device, true);
628
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700629 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
630 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
631 audio_extn_spkr_prot_is_enabled()) {
632 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800633 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700634 }
635 if (audio_extn_spkr_prot_start_processing(snd_device)) {
636 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800637 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700638 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700639 } else if (platform_can_split_snd_device(snd_device,
640 &num_devices,
641 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700642 for (i = 0; i < num_devices; i++) {
643 enable_snd_device(adev, new_snd_devices[i]);
644 }
vivek mehtab6506412015-08-07 16:55:17 -0700645 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700646 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800647 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
648 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
649 ALOGE(" %s: Invalid sound device returned", __func__);
650 goto on_error;
651 }
Ed Tam70b5c142016-03-21 19:14:29 -0700652
Eric Laurent2e140aa2016-06-30 17:14:46 -0700653 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800654 audio_route_apply_and_update_path(adev->audio_route, device_name);
655 }
656on_success:
657 adev->snd_dev_ref_cnt[snd_device]++;
658 ret_val = 0;
659on_error:
660 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800661}
662
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800663int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700664 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800665{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700666 int i, num_devices = 0;
667 snd_device_t new_snd_devices[2];
668
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800669 if (snd_device < SND_DEVICE_MIN ||
670 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800671 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800672 return -EINVAL;
673 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700674 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
675 ALOGE("%s: device ref cnt is already 0", __func__);
676 return -EINVAL;
677 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800678 audio_extn_tfa_98xx_disable_speaker(snd_device);
679
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700680 adev->snd_dev_ref_cnt[snd_device]--;
681 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800682 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700683 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
684 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
685 audio_extn_spkr_prot_is_enabled()) {
686 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700687 } else if (platform_can_split_snd_device(snd_device,
688 &num_devices,
689 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700690 for (i = 0; i < num_devices; i++) {
691 disable_snd_device(adev, new_snd_devices[i]);
692 }
vivek mehtab6506412015-08-07 16:55:17 -0700693 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700694 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800695 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
696 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
697 ALOGE(" %s: Invalid sound device returned", __func__);
698 return -EINVAL;
699 }
700
Eric Laurent2e140aa2016-06-30 17:14:46 -0700701 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800702 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700703 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700704 audio_extn_sound_trigger_update_device_status(snd_device,
705 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700706 }
vivek mehtab6506412015-08-07 16:55:17 -0700707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800708 return 0;
709}
710
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700711/*
712 legend:
713 uc - existing usecase
714 new_uc - new usecase
715 d1, d11, d2 - SND_DEVICE enums
716 a1, a2 - corresponding ANDROID device enums
717 B, B1, B2 - backend strings
718
719case 1
720 uc->dev d1 (a1) B1
721 new_uc->dev d1 (a1), d2 (a2) B1, B2
722
723 resolution: disable and enable uc->dev on d1
724
725case 2
726 uc->dev d1 (a1) B1
727 new_uc->dev d11 (a1) B1
728
729 resolution: need to switch uc since d1 and d11 are related
730 (e.g. speaker and voice-speaker)
731 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
732
733case 3
734 uc->dev d1 (a1) B1
735 new_uc->dev d2 (a2) B2
736
737 resolution: no need to switch uc
738
739case 4
740 uc->dev d1 (a1) B
741 new_uc->dev d2 (a2) B
742
743 resolution: disable enable uc-dev on d2 since backends match
744 we cannot enable two streams on two different devices if they
745 share the same backend. e.g. if offload is on speaker device using
746 QUAD_MI2S backend and a low-latency stream is started on voice-handset
747 using the same backend, offload must also be switched to voice-handset.
748
749case 5
750 uc->dev d1 (a1) B
751 new_uc->dev d1 (a1), d2 (a2) B
752
753 resolution: disable enable uc-dev on d2 since backends match
754 we cannot enable two streams on two different devices if they
755 share the same backend.
756
757case 6
758 uc->dev d1 a1 B1
759 new_uc->dev d2 a1 B2
760
761 resolution: no need to switch
762
763case 7
764
765 uc->dev d1 (a1), d2 (a2) B1, B2
766 new_uc->dev d1 B1
767
768 resolution: no need to switch
769
770*/
771static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
772 struct audio_usecase *new_uc,
773 snd_device_t new_snd_device)
774{
775 audio_devices_t a1 = uc->stream.out->devices;
776 audio_devices_t a2 = new_uc->stream.out->devices;
777
778 snd_device_t d1 = uc->out_snd_device;
779 snd_device_t d2 = new_snd_device;
780
781 // Treat as a special case when a1 and a2 are not disjoint
782 if ((a1 != a2) && (a1 & a2)) {
783 snd_device_t d3[2];
784 int num_devices = 0;
785 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
786 &num_devices,
787 d3);
788 if (ret < 0) {
789 if (ret != -ENOSYS) {
790 ALOGW("%s failed to split snd_device %d",
791 __func__,
792 popcount(a1) > 1 ? d1 : d2);
793 }
794 goto end;
795 }
796
797 // NB: case 7 is hypothetical and isn't a practical usecase yet.
798 // But if it does happen, we need to give priority to d2 if
799 // the combo devices active on the existing usecase share a backend.
800 // This is because we cannot have a usecase active on a combo device
801 // and a new usecase requests one device in this combo pair.
802 if (platform_check_backends_match(d3[0], d3[1])) {
803 return d2; // case 5
804 } else {
805 return d1; // case 1
806 }
807 } else {
808 if (platform_check_backends_match(d1, d2)) {
809 return d2; // case 2, 4
810 } else {
811 return d1; // case 6, 3
812 }
813 }
814
815end:
816 return d2; // return whatever was calculated before.
817}
818
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700819static void check_and_route_playback_usecases(struct audio_device *adev,
820 struct audio_usecase *uc_info,
821 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700822{
823 struct listnode *node;
824 struct audio_usecase *usecase;
825 bool switch_device[AUDIO_USECASE_MAX];
826 int i, num_uc_to_switch = 0;
827
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700828 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
829 uc_info,
830 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700831
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 /*
833 * This function is to make sure that all the usecases that are active on
834 * the hardware codec backend are always routed to any one device that is
835 * handled by the hardware codec.
836 * For example, if low-latency and deep-buffer usecases are currently active
837 * on speaker and out_set_parameters(headset) is received on low-latency
838 * output, then we have to make sure deep-buffer is also switched to headset,
839 * because of the limitation that both the devices cannot be enabled
840 * at the same time as they share the same backend.
841 */
842 /* Disable all the usecases on the shared backend other than the
843 specified usecase */
844 for (i = 0; i < AUDIO_USECASE_MAX; i++)
845 switch_device[i] = false;
846
847 list_for_each(node, &adev->usecase_list) {
848 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700849 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
850 continue;
851
852 if (force_routing ||
853 (usecase->out_snd_device != snd_device &&
854 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
855 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700856 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
857 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700858 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700859 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700860 switch_device[usecase->id] = true;
861 num_uc_to_switch++;
862 }
863 }
864
865 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700866 list_for_each(node, &adev->usecase_list) {
867 usecase = node_to_item(node, struct audio_usecase, list);
868 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700869 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900870 }
871 }
872
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700873 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900874 list_for_each(node, &adev->usecase_list) {
875 usecase = node_to_item(node, struct audio_usecase, list);
876 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700877 d_device = derive_playback_snd_device(usecase, uc_info,
878 snd_device);
879 enable_snd_device(adev, d_device);
880 /* Update the out_snd_device before enabling the audio route */
881 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 }
883 }
884
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 /* Re-route all the usecases on the shared backend other than the
886 specified usecase to new snd devices */
887 list_for_each(node, &adev->usecase_list) {
888 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700889 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700890 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700891 }
892 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 }
894}
895
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700896static void check_and_route_capture_usecases(struct audio_device *adev,
897 struct audio_usecase *uc_info,
898 snd_device_t snd_device)
899{
900 struct listnode *node;
901 struct audio_usecase *usecase;
902 bool switch_device[AUDIO_USECASE_MAX];
903 int i, num_uc_to_switch = 0;
904
vivek mehta4ed66e62016-04-15 23:33:34 -0700905 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
906
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700907 /*
908 * This function is to make sure that all the active capture usecases
909 * are always routed to the same input sound device.
910 * For example, if audio-record and voice-call usecases are currently
911 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
912 * is received for voice call then we have to make sure that audio-record
913 * usecase is also switched to earpiece i.e. voice-dmic-ef,
914 * because of the limitation that two devices cannot be enabled
915 * at the same time if they share the same backend.
916 */
917 for (i = 0; i < AUDIO_USECASE_MAX; i++)
918 switch_device[i] = false;
919
920 list_for_each(node, &adev->usecase_list) {
921 usecase = node_to_item(node, struct audio_usecase, list);
922 if (usecase->type != PCM_PLAYBACK &&
923 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700924 usecase->in_snd_device != snd_device &&
925 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700926 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
927 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700928 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700929 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700930 switch_device[usecase->id] = true;
931 num_uc_to_switch++;
932 }
933 }
934
935 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700936 list_for_each(node, &adev->usecase_list) {
937 usecase = node_to_item(node, struct audio_usecase, list);
938 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700939 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700940 }
941 }
942
943 list_for_each(node, &adev->usecase_list) {
944 usecase = node_to_item(node, struct audio_usecase, list);
945 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700946 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700947 }
948 }
949
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700950 /* Re-route all the usecases on the shared backend other than the
951 specified usecase to new snd devices */
952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 /* Update the in_snd_device only before enabling the audio route */
955 if (switch_device[usecase->id] ) {
956 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700957 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700958 }
959 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700960 }
961}
962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700964static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800965{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700966 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700967 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968
969 switch (channels) {
970 /*
971 * Do not handle stereo output in Multi-channel cases
972 * Stereo case is handled in normal playback path
973 */
974 case 6:
975 ALOGV("%s: HDMI supports 5.1", __func__);
976 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
977 break;
978 case 8:
979 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
980 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
981 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
982 break;
983 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700984 ALOGE("HDMI does not support multi channel playback");
985 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800986 break;
987 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700988 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800989}
990
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700991static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
992 uint32_t *supported_sample_rates __unused,
993 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800994{
Haynes Mathew George569b7482017-05-08 14:44:27 -0700995 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
996 supported_sample_rates,
997 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800998#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -0700999 for (ssize_t i=0; i<count; i++) {
1000 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1001 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001002 }
1003#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001004 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001005}
1006
Haynes Mathew George569b7482017-05-08 14:44:27 -07001007static int read_usb_sup_channel_masks(bool is_playback,
1008 audio_channel_mask_t *supported_channel_masks,
1009 uint32_t max_masks __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001011 int channels = audio_extn_usb_get_max_channels(is_playback);
1012 if (is_playback) {
1013 supported_channel_masks[0] =
1014 channels < 3 ? audio_channel_out_mask_from_count(channels) :
1015 audio_channel_mask_for_index_assignment_from_count(channels);
1016 } else {
1017 supported_channel_masks[0] = audio_channel_in_mask_from_count(channels);
1018 }
1019 ALOGV("%s: %s supported ch %d", __func__,
1020 is_playback ? "P" : "C", channels);
1021 return 1;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001022}
1023
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001024static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001025 audio_format_t *supported_formats,
1026 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001027{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001028 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001029 switch (bitwidth) {
1030 case 24:
1031 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001032 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001033 break;
1034 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001035 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001036 break;
1037 case 16:
1038 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001039 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001040 break;
1041 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001042 ALOGV("%s: %s supported format %d", __func__,
1043 is_playback ? "P" : "C", bitwidth);
1044 return 1;
1045}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001046
Haynes Mathew George569b7482017-05-08 14:44:27 -07001047static int read_usb_sup_params_and_compare(bool is_playback,
1048 audio_format_t *format,
1049 audio_format_t *supported_formats,
1050 uint32_t max_formats,
1051 audio_channel_mask_t *mask,
1052 audio_channel_mask_t *supported_channel_masks,
1053 uint32_t max_masks,
1054 uint32_t *rate,
1055 uint32_t *supported_sample_rates,
1056 uint32_t max_rates) {
1057 int ret = 0;
1058 int num_formats;
1059 int num_masks;
1060 int num_rates;
1061 int i;
1062
1063 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1064 max_formats);
1065 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1066 max_masks);
1067 num_rates = read_usb_sup_sample_rates(is_playback,
1068 supported_sample_rates, max_rates);
1069
1070#define LUT(table, len, what, dflt) \
1071 for (i=0; i<len && (table[i] != what); i++); \
1072 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1073
1074 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1075 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1076 LUT(supported_sample_rates, num_rates, *rate, 0);
1077
1078#undef LUT
1079 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001080}
1081
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001082static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1083{
1084 struct audio_usecase *usecase;
1085 struct listnode *node;
1086
1087 list_for_each(node, &adev->usecase_list) {
1088 usecase = node_to_item(node, struct audio_usecase, list);
1089 if (usecase->type == VOICE_CALL) {
1090 ALOGV("%s: usecase id %d", __func__, usecase->id);
1091 return usecase->id;
1092 }
1093 }
1094 return USECASE_INVALID;
1095}
1096
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001097struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1098 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001099{
1100 struct audio_usecase *usecase;
1101 struct listnode *node;
1102
1103 list_for_each(node, &adev->usecase_list) {
1104 usecase = node_to_item(node, struct audio_usecase, list);
1105 if (usecase->id == uc_id)
1106 return usecase;
1107 }
1108 return NULL;
1109}
1110
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001111int select_devices(struct audio_device *adev,
1112 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001113{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001114 snd_device_t out_snd_device = SND_DEVICE_NONE;
1115 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116 struct audio_usecase *usecase = NULL;
1117 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001118 struct audio_usecase *hfp_usecase = NULL;
1119 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001120 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001122
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001123 usecase = get_usecase_from_list(adev, uc_id);
1124 if (usecase == NULL) {
1125 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1126 return -EINVAL;
1127 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001128
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001129 if ((usecase->type == VOICE_CALL) ||
1130 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001131 out_snd_device = platform_get_output_snd_device(adev->platform,
1132 usecase->stream.out->devices);
1133 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 usecase->devices = usecase->stream.out->devices;
1135 } else {
1136 /*
1137 * If the voice call is active, use the sound devices of voice call usecase
1138 * so that it would not result any device switch. All the usecases will
1139 * be switched to new device when select_devices() is called for voice call
1140 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001141 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001142 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001143 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001144 vc_usecase = get_usecase_from_list(adev,
1145 get_voice_usecase_id_from_list(adev));
1146 if ((vc_usecase != NULL) &&
1147 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1148 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001149 in_snd_device = vc_usecase->in_snd_device;
1150 out_snd_device = vc_usecase->out_snd_device;
1151 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001152 } else if (audio_extn_hfp_is_active(adev)) {
1153 hfp_ucid = audio_extn_hfp_get_usecase();
1154 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1155 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1156 in_snd_device = hfp_usecase->in_snd_device;
1157 out_snd_device = hfp_usecase->out_snd_device;
1158 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001159 }
1160 if (usecase->type == PCM_PLAYBACK) {
1161 usecase->devices = usecase->stream.out->devices;
1162 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001163 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001164 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001165 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001166 if (usecase->stream.out == adev->primary_output &&
1167 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001168 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1169 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001170 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001171 select_devices(adev, adev->active_input->usecase);
1172 }
1173 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001174 } else if (usecase->type == PCM_CAPTURE) {
1175 usecase->devices = usecase->stream.in->device;
1176 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001177 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001178 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001179 if (adev->active_input &&
1180 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1181 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001182 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001183 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1184 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1185 } else if (adev->primary_output) {
1186 out_device = adev->primary_output->devices;
1187 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001188 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001189 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001190 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001191 }
1192 }
1193
1194 if (out_snd_device == usecase->out_snd_device &&
1195 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001196 return 0;
1197 }
1198
Eric Laurent2bafff12016-03-17 12:17:23 -07001199 if (out_snd_device != SND_DEVICE_NONE &&
1200 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1201 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1202 __func__,
1203 use_case_table[uc_id],
1204 adev->last_logged_snd_device[uc_id][0],
1205 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1206 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1207 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1208 -1,
1209 out_snd_device,
1210 platform_get_snd_device_name(out_snd_device),
1211 platform_get_snd_device_acdb_id(out_snd_device));
1212 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1213 }
1214 if (in_snd_device != SND_DEVICE_NONE &&
1215 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1216 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1217 __func__,
1218 use_case_table[uc_id],
1219 adev->last_logged_snd_device[uc_id][1],
1220 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1221 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1222 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1223 -1,
1224 in_snd_device,
1225 platform_get_snd_device_name(in_snd_device),
1226 platform_get_snd_device_acdb_id(in_snd_device));
1227 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1228 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001230 /*
1231 * Limitation: While in call, to do a device switch we need to disable
1232 * and enable both RX and TX devices though one of them is same as current
1233 * device.
1234 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001235 if ((usecase->type == VOICE_CALL) &&
1236 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1237 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001238 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001239 /* Disable sidetone only if voice call already exists */
1240 if (voice_is_call_state_active(adev))
1241 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001242 }
1243
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001244 /* Disable current sound devices */
1245 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001246 disable_audio_route(adev, usecase);
1247 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001248 }
1249
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001250 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001251 disable_audio_route(adev, usecase);
1252 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253 }
1254
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001255 /* Applicable only on the targets that has external modem.
1256 * New device information should be sent to modem before enabling
1257 * the devices to reduce in-call device switch time.
1258 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001259 if ((usecase->type == VOICE_CALL) &&
1260 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1261 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001262 status = platform_switch_voice_call_enable_device_config(adev->platform,
1263 out_snd_device,
1264 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001265 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001266
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001267 /* Enable new sound devices */
1268 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001269 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1270 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001271 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001272 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273 }
1274
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001275 if (in_snd_device != SND_DEVICE_NONE) {
1276 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001277 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001278 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001279
Eric Laurentb23d5282013-05-14 15:27:20 -07001280 if (usecase->type == VOICE_CALL)
1281 status = platform_switch_voice_call_device_post(adev->platform,
1282 out_snd_device,
1283 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001284
sangwoo170731f2013-06-08 15:36:36 +09001285 usecase->in_snd_device = in_snd_device;
1286 usecase->out_snd_device = out_snd_device;
1287
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001288 audio_extn_tfa_98xx_set_mode();
1289
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001290 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001291
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001292 /* Applicable only on the targets that has external modem.
1293 * Enable device command should be sent to modem only after
1294 * enabling voice call mixer controls
1295 */
vivek mehta765eb642015-08-07 19:46:06 -07001296 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001297 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1298 out_snd_device,
1299 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001300 /* Enable sidetone only if voice call already exists */
1301 if (voice_is_call_state_active(adev))
1302 voice_set_sidetone(adev, out_snd_device, true);
1303 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001305 return status;
1306}
1307
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001308static int stop_input_stream(struct stream_in *in)
1309{
1310 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001311 struct audio_usecase *uc_info;
1312 struct audio_device *adev = in->dev;
1313
Eric Laurentc8400632013-02-14 19:04:54 -08001314 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001315
Eric Laurent994a6932013-07-17 11:51:42 -07001316 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001317 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318 uc_info = get_usecase_from_list(adev, in->usecase);
1319 if (uc_info == NULL) {
1320 ALOGE("%s: Could not find the usecase (%d) in the list",
1321 __func__, in->usecase);
1322 return -EINVAL;
1323 }
1324
vivek mehta781065c2017-04-04 12:55:01 -07001325 /* Close in-call recording streams */
1326 voice_check_and_stop_incall_rec_usecase(adev, in);
1327
Eric Laurent150dbfe2013-02-27 14:31:02 -08001328 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001329 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001330
1331 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001332 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001333
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001334 list_remove(&uc_info->list);
1335 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001336
Eric Laurent994a6932013-07-17 11:51:42 -07001337 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001338 return ret;
1339}
1340
1341int start_input_stream(struct stream_in *in)
1342{
1343 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001344 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001345 struct audio_usecase *uc_info;
1346 struct audio_device *adev = in->dev;
1347
Eric Laurent994a6932013-07-17 11:51:42 -07001348 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001349
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001350 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1351 return -EIO;
1352
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001353 if (in->card_status == CARD_STATUS_OFFLINE ||
1354 adev->card_status == CARD_STATUS_OFFLINE) {
1355 ALOGW("in->card_status or adev->card_status offline, try again");
1356 ret = -EAGAIN;
1357 goto error_config;
1358 }
1359
vivek mehta781065c2017-04-04 12:55:01 -07001360 /* Check if source matches incall recording usecase criteria */
1361 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1362 if (ret)
1363 goto error_config;
1364 else
1365 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1366
Eric Laurentb23d5282013-05-14 15:27:20 -07001367 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001368 if (in->pcm_device_id < 0) {
1369 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1370 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001371 ret = -EINVAL;
1372 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001374
1375 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001376 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1377 uc_info->id = in->usecase;
1378 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001379 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001380 uc_info->devices = in->device;
1381 uc_info->in_snd_device = SND_DEVICE_NONE;
1382 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001383
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001384 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001385
1386 audio_extn_perf_lock_acquire();
1387
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001388 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001389
Eric Laurent0e46adf2016-12-16 12:49:24 -08001390 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001391 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001392 ALOGE("%s: pcm stream not ready", __func__);
1393 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001394 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001395 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001396 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001397 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1398 goto error_open;
1399 }
1400 } else {
1401 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1402 unsigned int pcm_open_retry_count = 0;
1403
1404 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1405 flags |= PCM_MMAP | PCM_NOIRQ;
1406 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1407 } else if (in->realtime) {
1408 flags |= PCM_MMAP | PCM_NOIRQ;
1409 }
1410
1411 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1412 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1413
1414 while (1) {
1415 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1416 flags, &in->config);
1417 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1418 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1419 if (in->pcm != NULL) {
1420 pcm_close(in->pcm);
1421 in->pcm = NULL;
1422 }
1423 if (pcm_open_retry_count-- == 0) {
1424 ret = -EIO;
1425 goto error_open;
1426 }
1427 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1428 continue;
1429 }
1430 break;
1431 }
1432
1433 ALOGV("%s: pcm_prepare", __func__);
1434 ret = pcm_prepare(in->pcm);
1435 if (ret < 0) {
1436 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001437 pcm_close(in->pcm);
1438 in->pcm = NULL;
1439 goto error_open;
1440 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001441 if (in->realtime) {
1442 ret = pcm_start(in->pcm);
1443 if (ret < 0) {
1444 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1445 pcm_close(in->pcm);
1446 in->pcm = NULL;
1447 goto error_open;
1448 }
1449 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001450 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001451 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001452 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001453 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001454
Eric Laurent0e46adf2016-12-16 12:49:24 -08001455 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001456
1457error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001459 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001460
1461error_config:
1462 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001463 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001464 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465}
1466
Eric Laurenta1478072015-09-21 17:21:52 -07001467void lock_input_stream(struct stream_in *in)
1468{
1469 pthread_mutex_lock(&in->pre_lock);
1470 pthread_mutex_lock(&in->lock);
1471 pthread_mutex_unlock(&in->pre_lock);
1472}
1473
1474void lock_output_stream(struct stream_out *out)
1475{
1476 pthread_mutex_lock(&out->pre_lock);
1477 pthread_mutex_lock(&out->lock);
1478 pthread_mutex_unlock(&out->pre_lock);
1479}
1480
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001481/* must be called with out->lock locked */
1482static int send_offload_cmd_l(struct stream_out* out, int command)
1483{
1484 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1485
1486 ALOGVV("%s %d", __func__, command);
1487
1488 cmd->cmd = command;
1489 list_add_tail(&out->offload_cmd_list, &cmd->node);
1490 pthread_cond_signal(&out->offload_cond);
1491 return 0;
1492}
1493
1494/* must be called iwth out->lock locked */
1495static void stop_compressed_output_l(struct stream_out *out)
1496{
1497 out->offload_state = OFFLOAD_STATE_IDLE;
1498 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001499 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001500 if (out->compr != NULL) {
1501 compress_stop(out->compr);
1502 while (out->offload_thread_blocked) {
1503 pthread_cond_wait(&out->cond, &out->lock);
1504 }
1505 }
1506}
1507
1508static void *offload_thread_loop(void *context)
1509{
1510 struct stream_out *out = (struct stream_out *) context;
1511 struct listnode *item;
1512
1513 out->offload_state = OFFLOAD_STATE_IDLE;
1514 out->playback_started = 0;
1515
1516 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1517 set_sched_policy(0, SP_FOREGROUND);
1518 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1519
1520 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001521 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001522 for (;;) {
1523 struct offload_cmd *cmd = NULL;
1524 stream_callback_event_t event;
1525 bool send_callback = false;
1526
1527 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1528 __func__, list_empty(&out->offload_cmd_list),
1529 out->offload_state);
1530 if (list_empty(&out->offload_cmd_list)) {
1531 ALOGV("%s SLEEPING", __func__);
1532 pthread_cond_wait(&out->offload_cond, &out->lock);
1533 ALOGV("%s RUNNING", __func__);
1534 continue;
1535 }
1536
1537 item = list_head(&out->offload_cmd_list);
1538 cmd = node_to_item(item, struct offload_cmd, node);
1539 list_remove(item);
1540
1541 ALOGVV("%s STATE %d CMD %d out->compr %p",
1542 __func__, out->offload_state, cmd->cmd, out->compr);
1543
1544 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1545 free(cmd);
1546 break;
1547 }
1548
1549 if (out->compr == NULL) {
1550 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001551 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001552 pthread_cond_signal(&out->cond);
1553 continue;
1554 }
1555 out->offload_thread_blocked = true;
1556 pthread_mutex_unlock(&out->lock);
1557 send_callback = false;
1558 switch(cmd->cmd) {
1559 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1560 compress_wait(out->compr, -1);
1561 send_callback = true;
1562 event = STREAM_CBK_EVENT_WRITE_READY;
1563 break;
1564 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001565 compress_next_track(out->compr);
1566 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001567 send_callback = true;
1568 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001569 /* Resend the metadata for next iteration */
1570 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001571 break;
1572 case OFFLOAD_CMD_DRAIN:
1573 compress_drain(out->compr);
1574 send_callback = true;
1575 event = STREAM_CBK_EVENT_DRAIN_READY;
1576 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001577 case OFFLOAD_CMD_ERROR:
1578 send_callback = true;
1579 event = STREAM_CBK_EVENT_ERROR;
1580 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001581 default:
1582 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1583 break;
1584 }
Eric Laurenta1478072015-09-21 17:21:52 -07001585 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001586 out->offload_thread_blocked = false;
1587 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001588 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001589 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001590 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001591 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001592 free(cmd);
1593 }
1594
1595 pthread_cond_signal(&out->cond);
1596 while (!list_empty(&out->offload_cmd_list)) {
1597 item = list_head(&out->offload_cmd_list);
1598 list_remove(item);
1599 free(node_to_item(item, struct offload_cmd, node));
1600 }
1601 pthread_mutex_unlock(&out->lock);
1602
1603 return NULL;
1604}
1605
1606static int create_offload_callback_thread(struct stream_out *out)
1607{
1608 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1609 list_init(&out->offload_cmd_list);
1610 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1611 offload_thread_loop, out);
1612 return 0;
1613}
1614
1615static int destroy_offload_callback_thread(struct stream_out *out)
1616{
Eric Laurenta1478072015-09-21 17:21:52 -07001617 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001618 stop_compressed_output_l(out);
1619 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1620
1621 pthread_mutex_unlock(&out->lock);
1622 pthread_join(out->offload_thread, (void **) NULL);
1623 pthread_cond_destroy(&out->offload_cond);
1624
1625 return 0;
1626}
1627
Eric Laurent07eeafd2013-10-06 12:52:49 -07001628static bool allow_hdmi_channel_config(struct audio_device *adev)
1629{
1630 struct listnode *node;
1631 struct audio_usecase *usecase;
1632 bool ret = true;
1633
1634 list_for_each(node, &adev->usecase_list) {
1635 usecase = node_to_item(node, struct audio_usecase, list);
1636 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1637 /*
1638 * If voice call is already existing, do not proceed further to avoid
1639 * disabling/enabling both RX and TX devices, CSD calls, etc.
1640 * Once the voice call done, the HDMI channels can be configured to
1641 * max channels of remaining use cases.
1642 */
1643 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001644 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001645 __func__);
1646 ret = false;
1647 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001648 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1649 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001650 "no change in HDMI channels", __func__);
1651 ret = false;
1652 break;
1653 }
1654 }
1655 }
1656 return ret;
1657}
1658
1659static int check_and_set_hdmi_channels(struct audio_device *adev,
1660 unsigned int channels)
1661{
1662 struct listnode *node;
1663 struct audio_usecase *usecase;
1664
1665 /* Check if change in HDMI channel config is allowed */
1666 if (!allow_hdmi_channel_config(adev))
1667 return 0;
1668
1669 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001670 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001671 return 0;
1672 }
1673
1674 platform_set_hdmi_channels(adev->platform, channels);
1675 adev->cur_hdmi_channels = channels;
1676
1677 /*
1678 * Deroute all the playback streams routed to HDMI so that
1679 * the back end is deactivated. Note that backend will not
1680 * be deactivated if any one stream is connected to it.
1681 */
1682 list_for_each(node, &adev->usecase_list) {
1683 usecase = node_to_item(node, struct audio_usecase, list);
1684 if (usecase->type == PCM_PLAYBACK &&
1685 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001686 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001687 }
1688 }
1689
1690 /*
1691 * Enable all the streams disabled above. Now the HDMI backend
1692 * will be activated with new channel configuration
1693 */
1694 list_for_each(node, &adev->usecase_list) {
1695 usecase = node_to_item(node, struct audio_usecase, list);
1696 if (usecase->type == PCM_PLAYBACK &&
1697 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001698 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001699 }
1700 }
1701
1702 return 0;
1703}
1704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705static int stop_output_stream(struct stream_out *out)
1706{
1707 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708 struct audio_usecase *uc_info;
1709 struct audio_device *adev = out->dev;
1710
Eric Laurent994a6932013-07-17 11:51:42 -07001711 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001712 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713 uc_info = get_usecase_from_list(adev, out->usecase);
1714 if (uc_info == NULL) {
1715 ALOGE("%s: Could not find the usecase (%d) in the list",
1716 __func__, out->usecase);
1717 return -EINVAL;
1718 }
1719
Haynes Mathew George41f86652014-06-17 14:22:15 -07001720 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1721 if (adev->visualizer_stop_output != NULL)
1722 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1723 if (adev->offload_effects_stop_output != NULL)
1724 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1725 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001726
Eric Laurent150dbfe2013-02-27 14:31:02 -08001727 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001728 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001729
1730 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001731 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001733 list_remove(&uc_info->list);
1734 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735
Eric Laurent0499d4f2014-08-25 22:39:29 -05001736 audio_extn_extspk_update(adev->extspk);
1737
Eric Laurent07eeafd2013-10-06 12:52:49 -07001738 /* Must be called after removing the usecase from list */
1739 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1740 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1741
Eric Laurent994a6932013-07-17 11:51:42 -07001742 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 return ret;
1744}
1745
1746int start_output_stream(struct stream_out *out)
1747{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 struct audio_usecase *uc_info;
1750 struct audio_device *adev = out->dev;
1751
Eric Laurent994a6932013-07-17 11:51:42 -07001752 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001753 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001754
1755 if (out->card_status == CARD_STATUS_OFFLINE ||
1756 adev->card_status == CARD_STATUS_OFFLINE) {
1757 ALOGW("out->card_status or adev->card_status offline, try again");
1758 ret = -EAGAIN;
1759 goto error_config;
1760 }
1761
Eric Laurentb23d5282013-05-14 15:27:20 -07001762 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763 if (out->pcm_device_id < 0) {
1764 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1765 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001766 ret = -EINVAL;
1767 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 }
1769
1770 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1771 uc_info->id = out->usecase;
1772 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001773 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001774 uc_info->devices = out->devices;
1775 uc_info->in_snd_device = SND_DEVICE_NONE;
1776 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777
Eric Laurent07eeafd2013-10-06 12:52:49 -07001778 /* This must be called before adding this usecase to the list */
1779 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1780 check_and_set_hdmi_channels(adev, out->config.channels);
1781
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001782 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001784 audio_extn_perf_lock_acquire();
1785
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001786 select_devices(adev, out->usecase);
1787
Eric Laurent0499d4f2014-08-25 22:39:29 -05001788 audio_extn_extspk_update(adev->extspk);
1789
Andy Hung31aca912014-03-20 17:14:59 -07001790 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001791 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001792 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1793 out->pcm = NULL;
1794 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1795 COMPRESS_IN, &out->compr_config);
1796 if (out->compr && !is_compress_ready(out->compr)) {
1797 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1798 compress_close(out->compr);
1799 out->compr = NULL;
1800 ret = -EIO;
1801 goto error_open;
1802 }
1803 if (out->offload_callback)
1804 compress_nonblock(out->compr, out->non_blocking);
1805
1806 if (adev->visualizer_start_output != NULL)
1807 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1808 if (adev->offload_effects_start_output != NULL)
1809 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1810 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001811 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001812 ALOGE("%s: pcm stream not ready", __func__);
1813 goto error_open;
1814 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001815 ret = pcm_start(out->pcm);
1816 if (ret < 0) {
1817 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1818 goto error_open;
1819 }
1820 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001821 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001822 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001823
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001824 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1825 flags |= PCM_MMAP | PCM_NOIRQ;
1826 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001827 } else if (out->realtime) {
1828 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001829 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001830
1831 while (1) {
1832 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1833 flags, &out->config);
1834 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1835 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1836 if (out->pcm != NULL) {
1837 pcm_close(out->pcm);
1838 out->pcm = NULL;
1839 }
1840 if (pcm_open_retry_count-- == 0) {
1841 ret = -EIO;
1842 goto error_open;
1843 }
1844 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1845 continue;
1846 }
1847 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001848 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001849 ALOGV("%s: pcm_prepare", __func__);
1850 if (pcm_is_ready(out->pcm)) {
1851 ret = pcm_prepare(out->pcm);
1852 if (ret < 0) {
1853 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1854 pcm_close(out->pcm);
1855 out->pcm = NULL;
1856 goto error_open;
1857 }
1858 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001859 if (out->realtime) {
1860 ret = pcm_start(out->pcm);
1861 if (ret < 0) {
1862 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1863 pcm_close(out->pcm);
1864 out->pcm = NULL;
1865 goto error_open;
1866 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001867 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001868 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001869 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001870 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001871 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001872 audio_extn_utils_send_app_type_gain(out->dev,
1873 out->app_type_cfg.app_type,
1874 &out->app_type_cfg.gain[0]);
Eric Laurent994a6932013-07-17 11:51:42 -07001875 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001876 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001877error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001878 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001880error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001881 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882}
1883
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884static int check_input_parameters(uint32_t sample_rate,
1885 audio_format_t format,
1886 int channel_count)
1887{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001888 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1889 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
1890 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED)) {
vivek mehtadae44712015-07-27 14:13:18 -07001891 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1892 return -EINVAL;
1893 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894
vivek mehtadae44712015-07-27 14:13:18 -07001895 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001896 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001897 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1898 return -EINVAL;
1899 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900
1901 switch (sample_rate) {
1902 case 8000:
1903 case 11025:
1904 case 12000:
1905 case 16000:
1906 case 22050:
1907 case 24000:
1908 case 32000:
1909 case 44100:
1910 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001911 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912 break;
1913 default:
vivek mehtadae44712015-07-27 14:13:18 -07001914 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915 return -EINVAL;
1916 }
1917
1918 return 0;
1919}
1920
vivek mehtaa68fea62017-06-08 19:04:02 -07001921static size_t get_stream_buffer_size(size_t duration_ms,
1922 uint32_t sample_rate,
1923 audio_format_t format,
1924 int channel_count,
1925 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926{
1927 size_t size = 0;
1928
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001929 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1930 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931
vivek mehtaa68fea62017-06-08 19:04:02 -07001932 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001933 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001934 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001935
1936 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937
Glenn Kasten4f993392014-05-14 07:30:48 -07001938 /* make sure the size is multiple of 32 bytes
1939 * At 48 kHz mono 16-bit PCM:
1940 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1941 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1942 */
1943 size += 0x1f;
1944 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001945
1946 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947}
1948
1949static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1950{
1951 struct stream_out *out = (struct stream_out *)stream;
1952
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001953 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954}
1955
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001956static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957{
1958 return -ENOSYS;
1959}
1960
1961static size_t out_get_buffer_size(const struct audio_stream *stream)
1962{
1963 struct stream_out *out = (struct stream_out *)stream;
1964
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001965 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1966 return out->compr_config.fragment_size;
1967 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001968 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001969 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970}
1971
1972static uint32_t out_get_channels(const struct audio_stream *stream)
1973{
1974 struct stream_out *out = (struct stream_out *)stream;
1975
1976 return out->channel_mask;
1977}
1978
1979static audio_format_t out_get_format(const struct audio_stream *stream)
1980{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001981 struct stream_out *out = (struct stream_out *)stream;
1982
1983 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984}
1985
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001986static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987{
1988 return -ENOSYS;
1989}
1990
1991static int out_standby(struct audio_stream *stream)
1992{
1993 struct stream_out *out = (struct stream_out *)stream;
1994 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001995 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001996
Eric Laurent994a6932013-07-17 11:51:42 -07001997 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001998 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999
Eric Laurenta1478072015-09-21 17:21:52 -07002000 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002002 if (adev->adm_deregister_stream)
2003 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002004 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002006 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2007 if (out->pcm) {
2008 pcm_close(out->pcm);
2009 out->pcm = NULL;
2010 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002011 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002012 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002013 out->playback_started = false;
2014 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002015 } else {
2016 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002017 out->gapless_mdata.encoder_delay = 0;
2018 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019 if (out->compr != NULL) {
2020 compress_close(out->compr);
2021 out->compr = NULL;
2022 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002023 }
Phil Burkbc991042017-02-24 08:06:44 -08002024 if (do_stop) {
2025 stop_output_stream(out);
2026 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002027 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028 }
2029 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002030 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031 return 0;
2032}
2033
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002034static int out_on_error(struct audio_stream *stream)
2035{
2036 struct stream_out *out = (struct stream_out *)stream;
2037 struct audio_device *adev = out->dev;
2038 bool do_standby = false;
2039
2040 lock_output_stream(out);
2041 if (!out->standby) {
2042 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2043 stop_compressed_output_l(out);
2044 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2045 } else
2046 do_standby = true;
2047 }
2048 pthread_mutex_unlock(&out->lock);
2049
2050 if (do_standby)
2051 return out_standby(&out->stream.common);
2052
2053 return 0;
2054}
2055
Andy Hung7401c7c2016-09-21 12:41:21 -07002056static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002057{
Andy Hung7401c7c2016-09-21 12:41:21 -07002058 struct stream_out *out = (struct stream_out *)stream;
2059
2060 // We try to get the lock for consistency,
2061 // but it isn't necessary for these variables.
2062 // If we're not in standby, we may be blocked on a write.
2063 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2064 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2065 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2066
2067 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002068 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002069 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002070
2071 // dump error info
2072 (void)error_log_dump(
2073 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002074 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002075 (void)power_log_dump(
2076 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077 return 0;
2078}
2079
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002080static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2081{
2082 int ret = 0;
2083 char value[32];
2084 struct compr_gapless_mdata tmp_mdata;
2085
2086 if (!out || !parms) {
2087 return -EINVAL;
2088 }
2089
2090 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2091 if (ret >= 0) {
2092 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2093 } else {
2094 return -EINVAL;
2095 }
2096
2097 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2098 if (ret >= 0) {
2099 tmp_mdata.encoder_padding = atoi(value);
2100 } else {
2101 return -EINVAL;
2102 }
2103
2104 out->gapless_mdata = tmp_mdata;
2105 out->send_new_metadata = 1;
2106 ALOGV("%s new encoder delay %u and padding %u", __func__,
2107 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2108
2109 return 0;
2110}
2111
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002112static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2113{
2114 return out == adev->primary_output || out == adev->voice_tx_output;
2115}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2118{
2119 struct stream_out *out = (struct stream_out *)stream;
2120 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002121 struct audio_usecase *usecase;
2122 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123 struct str_parms *parms;
2124 char value[32];
2125 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002126 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002127 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128
Eric Laurent2e140aa2016-06-30 17:14:46 -07002129 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002130 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 parms = str_parms_create_str(kvpairs);
2132 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2133 if (ret >= 0) {
2134 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002135 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002136 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002137
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002138 /*
2139 * When HDMI cable is unplugged the music playback is paused and
2140 * the policy manager sends routing=0. But the audioflinger
2141 * continues to write data until standby time (3sec).
2142 * As the HDMI core is turned off, the write gets blocked.
2143 * Avoid this by routing audio to speaker until standby.
2144 */
2145 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2146 val == AUDIO_DEVICE_NONE) {
2147 val = AUDIO_DEVICE_OUT_SPEAKER;
2148 }
2149
2150 /*
2151 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002152 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002153 * the select_devices(). But how do we undo this?
2154 *
2155 * For example, music playback is active on headset (deep-buffer usecase)
2156 * and if we go to ringtones and select a ringtone, low-latency usecase
2157 * will be started on headset+speaker. As we can't enable headset+speaker
2158 * and headset devices at the same time, select_devices() switches the music
2159 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2160 * So when the ringtone playback is completed, how do we undo the same?
2161 *
2162 * We are relying on the out_set_parameters() call on deep-buffer output,
2163 * once the ringtone playback is ended.
2164 * NOTE: We should not check if the current devices are same as new devices.
2165 * Because select_devices() must be called to switch back the music
2166 * playback to headset.
2167 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002168 audio_devices_t new_dev = val;
2169 if (new_dev != AUDIO_DEVICE_NONE) {
2170 bool same_dev = out->devices == new_dev;
2171 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002172
Eric Laurenta7657192014-10-09 21:09:33 -07002173 if (output_drives_call(adev, out)) {
2174 if (!voice_is_in_call(adev)) {
2175 if (adev->mode == AUDIO_MODE_IN_CALL) {
2176 adev->current_call_output = out;
2177 ret = voice_start_call(adev);
2178 }
2179 } else {
2180 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002181 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002182 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002183 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002184
2185 if (!out->standby) {
2186 if (!same_dev) {
2187 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002188 // inform adm before actual routing to prevent glitches.
2189 if (adev->adm_on_routing_change) {
2190 adev->adm_on_routing_change(adev->adm_data,
2191 out->handle);
2192 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002193 }
2194 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002195 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002196 }
2197
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002198 }
2199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002201 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002202
2203 /*handles device and call state changes*/
2204 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002206
2207 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2208 parse_compress_metadata(out, parms);
2209 }
2210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002212 ALOGV("%s: exit: code(%d)", __func__, status);
2213 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214}
2215
Haynes Mathew George569b7482017-05-08 14:44:27 -07002216static bool stream_get_parameter_channels(struct str_parms *query,
2217 struct str_parms *reply,
2218 audio_channel_mask_t *supported_channel_masks) {
2219 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002222 size_t i, j;
2223
2224 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2225 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 value[0] = '\0';
2227 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002228 while (supported_channel_masks[i] != 0) {
2229 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2230 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002231 if (!first) {
2232 strcat(value, "|");
2233 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002234 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 first = false;
2236 break;
2237 }
2238 }
2239 i++;
2240 }
2241 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002242 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002243 return ret >= 0;
2244}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002245
Haynes Mathew George569b7482017-05-08 14:44:27 -07002246static bool stream_get_parameter_formats(struct str_parms *query,
2247 struct str_parms *reply,
2248 audio_format_t *supported_formats) {
2249 int ret = -1;
2250 char value[256];
2251 int i;
2252
2253 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2254 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002255 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002256 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002257 case AUDIO_FORMAT_PCM_16_BIT:
2258 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2259 break;
2260 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2261 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2262 break;
2263 case AUDIO_FORMAT_PCM_32_BIT:
2264 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2265 break;
2266 default:
2267 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002268 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002269 break;
2270 }
2271 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002272 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002273 return ret >= 0;
2274}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002275
Haynes Mathew George569b7482017-05-08 14:44:27 -07002276static bool stream_get_parameter_rates(struct str_parms *query,
2277 struct str_parms *reply,
2278 uint32_t *supported_sample_rates) {
2279
2280 int i;
2281 char value[256];
2282 int ret = -1;
2283 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2284 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002285 value[0] = '\0';
2286 i=0;
2287 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002288 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002289 int avail = sizeof(value) - cursor;
2290 ret = snprintf(value + cursor, avail, "%s%d",
2291 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002292 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002293 if (ret < 0 || ret >= avail) {
2294 // if cursor is at the last element of the array
2295 // overwrite with \0 is duplicate work as
2296 // snprintf already put a \0 in place.
2297 // else
2298 // we had space to write the '|' at value[cursor]
2299 // (which will be overwritten) or no space to fill
2300 // the first element (=> cursor == 0)
2301 value[cursor] = '\0';
2302 break;
2303 }
2304 cursor += ret;
2305 ++i;
2306 }
2307 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2308 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002309 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002310 return ret >= 0;
2311}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002312
Haynes Mathew George569b7482017-05-08 14:44:27 -07002313static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2314{
2315 struct stream_out *out = (struct stream_out *)stream;
2316 struct str_parms *query = str_parms_create_str(keys);
2317 char *str;
2318 struct str_parms *reply = str_parms_create();
2319 bool replied = false;
2320 ALOGV("%s: enter: keys - %s", __func__, keys);
2321
2322 replied |= stream_get_parameter_channels(query, reply,
2323 &out->supported_channel_masks[0]);
2324 replied |= stream_get_parameter_formats(query, reply,
2325 &out->supported_formats[0]);
2326 replied |= stream_get_parameter_rates(query, reply,
2327 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002328 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002329 str = str_parms_to_str(reply);
2330 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002331 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002332 }
2333 str_parms_destroy(query);
2334 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002335 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336 return str;
2337}
2338
2339static uint32_t out_get_latency(const struct audio_stream_out *stream)
2340{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002341 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002342 struct stream_out *out = (struct stream_out *)stream;
2343
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002344 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2345 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002346 else if ((out->realtime) ||
2347 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002348 // since the buffer won't be filled up faster than realtime,
2349 // return a smaller number
2350 period_ms = (out->af_period_multiplier * out->config.period_size *
2351 1000) / (out->config.rate);
2352 hw_delay = platform_render_latency(out->usecase)/1000;
2353 return period_ms + hw_delay;
2354 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355
2356 return (out->config.period_count * out->config.period_size * 1000) /
2357 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358}
2359
2360static int out_set_volume(struct audio_stream_out *stream, float left,
2361 float right)
2362{
Eric Laurenta9024de2013-04-04 09:19:12 -07002363 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 int volume[2];
2365
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002366 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002367 /* only take left channel into account: the API is for stereo anyway */
2368 out->muted = (left == 0.0f);
2369 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002370 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2371 const char *mixer_ctl_name = "Compress Playback Volume";
2372 struct audio_device *adev = out->dev;
2373 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2375 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002376 /* try with the control based on device id */
2377 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2378 PCM_PLAYBACK);
2379 char ctl_name[128] = {0};
2380 snprintf(ctl_name, sizeof(ctl_name),
2381 "Compress Playback %d Volume", pcm_device_id);
2382 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2383 if (!ctl) {
2384 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2385 return -EINVAL;
2386 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 }
2388 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2389 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2390 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2391 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002392 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002393 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2394 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2395 if (!out->standby) {
2396 // if in standby, cached volume will be sent after stream is opened
2397 audio_extn_utils_send_app_type_gain(out->dev,
2398 out->app_type_cfg.app_type,
2399 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002400 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002401 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002402 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404 return -ENOSYS;
2405}
2406
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002407// note: this call is safe only if the stream_cb is
2408// removed first in close_output_stream (as is done now).
2409static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2410{
2411 if (!stream || !parms)
2412 return;
2413
2414 struct stream_out *out = (struct stream_out *)stream;
2415 struct audio_device *adev = out->dev;
2416
2417 card_status_t status;
2418 int card;
2419 if (parse_snd_card_status(parms, &card, &status) < 0)
2420 return;
2421
2422 pthread_mutex_lock(&adev->lock);
2423 bool valid_cb = (card == adev->snd_card);
2424 pthread_mutex_unlock(&adev->lock);
2425
2426 if (!valid_cb)
2427 return;
2428
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002429 lock_output_stream(out);
2430 if (out->card_status != status)
2431 out->card_status = status;
2432 pthread_mutex_unlock(&out->lock);
2433
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002434 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2435 use_case_table[out->usecase],
2436 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2437
2438 if (status == CARD_STATUS_OFFLINE)
2439 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002440
2441 return;
2442}
2443
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002444#ifdef NO_AUDIO_OUT
2445static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002446 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002447{
2448 struct stream_out *out = (struct stream_out *)stream;
2449
2450 /* No Output device supported other than BT for playback.
2451 * Sleep for the amount of buffer duration
2452 */
Eric Laurenta1478072015-09-21 17:21:52 -07002453 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002454 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2455 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002456 out_get_sample_rate(&out->stream.common));
2457 pthread_mutex_unlock(&out->lock);
2458 return bytes;
2459}
2460#endif
2461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2463 size_t bytes)
2464{
2465 struct stream_out *out = (struct stream_out *)stream;
2466 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002467 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002468 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469
Eric Laurenta1478072015-09-21 17:21:52 -07002470 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002471 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002472 const size_t frame_size = audio_stream_out_frame_size(stream);
2473 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002474
Eric Laurent0e46adf2016-12-16 12:49:24 -08002475 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2476 error_code = ERROR_CODE_WRITE;
2477 goto exit;
2478 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002480 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002481 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002482 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002483 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002484 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002486 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487 goto exit;
2488 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002489
2490 if (last_known_cal_step != -1) {
2491 ALOGD("%s: retry previous failed cal level set", __func__);
2492 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2493 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002496 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002497 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002498 if (out->send_new_metadata) {
2499 ALOGVV("send new gapless metadata");
2500 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2501 out->send_new_metadata = 0;
2502 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002503 unsigned int avail;
2504 struct timespec tstamp;
2505 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2506 /* Do not limit write size if the available frames count is unknown */
2507 if (ret != 0) {
2508 avail = bytes;
2509 }
2510 if (avail == 0) {
2511 ret = 0;
2512 } else {
2513 if (avail > bytes) {
2514 avail = bytes;
2515 }
2516 ret = compress_write(out->compr, buffer, avail);
2517 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2518 __func__, avail, ret);
2519 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002520
Eric Laurent6e895242013-09-05 16:10:57 -07002521 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002522 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2523 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002524 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002525 compress_start(out->compr);
2526 out->playback_started = 1;
2527 out->offload_state = OFFLOAD_STATE_PLAYING;
2528 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002529 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002530 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002531 } else {
2532 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002533 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002535 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002536 return ret;
2537 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002538 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002539 if (out->pcm) {
2540 if (out->muted)
2541 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002542
Eric Laurent0e46adf2016-12-16 12:49:24 -08002543 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002544
Haynes Mathew George03c40102016-01-29 17:57:48 -08002545 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2546 out->config.rate;
2547 request_out_focus(out, ns);
2548
2549 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2550 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002551 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002552 else
2553 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002554
Haynes Mathew George03c40102016-01-29 17:57:48 -08002555 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002556 } else {
2557 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002558 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559 }
2560
2561exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002562 // For PCM we always consume the buffer and return #bytes regardless of ret.
2563 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002564 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002565 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002566 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002567
2568 // only get time if needed for logging, as it is a system call on 32 bit devices.
2569 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2570 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2571 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002572
Andy Hung7401c7c2016-09-21 12:41:21 -07002573 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002574 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002575 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2576 ALOGE_IF(out->pcm != NULL,
2577 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002578 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002579 // usleep not guaranteed for values over 1 second but we don't limit here.
2580 }
2581 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 pthread_mutex_unlock(&out->lock);
2584
2585 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002586 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002587 if (sleeptime_us != 0)
2588 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002589 } else {
2590 // only log if the data is properly written (out->power_log may be null)
Andy Hung8e7f03f2017-06-12 14:05:22 -07002591 power_log_log(out->power_log, buffer, frames, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 }
2593 return bytes;
2594}
2595
2596static int out_get_render_position(const struct audio_stream_out *stream,
2597 uint32_t *dsp_frames)
2598{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002599 struct stream_out *out = (struct stream_out *)stream;
2600 *dsp_frames = 0;
2601 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002602 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002603 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002604 unsigned long frames = 0;
2605 // TODO: check return value
2606 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2607 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002608 ALOGVV("%s rendered frames %d sample_rate %d",
2609 __func__, *dsp_frames, out->sample_rate);
2610 }
2611 pthread_mutex_unlock(&out->lock);
2612 return 0;
2613 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002614 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615}
2616
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002617static int out_add_audio_effect(const struct audio_stream *stream __unused,
2618 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619{
2620 return 0;
2621}
2622
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002623static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2624 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625{
2626 return 0;
2627}
2628
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002629static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2630 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002632 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633}
2634
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002635static int out_get_presentation_position(const struct audio_stream_out *stream,
2636 uint64_t *frames, struct timespec *timestamp)
2637{
2638 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002639 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002640 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002641
Eric Laurenta1478072015-09-21 17:21:52 -07002642 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002643
Eric Laurent949a0892013-09-20 09:20:13 -07002644 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2645 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002646 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002647 compress_get_tstamp(out->compr, &dsp_frames,
2648 &out->sample_rate);
2649 ALOGVV("%s rendered frames %ld sample_rate %d",
2650 __func__, dsp_frames, out->sample_rate);
2651 *frames = dsp_frames;
2652 ret = 0;
2653 /* this is the best we can do */
2654 clock_gettime(CLOCK_MONOTONIC, timestamp);
2655 }
2656 } else {
2657 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002658 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002659 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2660 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002661 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002662 // This adjustment accounts for buffering after app processor.
2663 // It is based on estimated DSP latency per use case, rather than exact.
2664 signed_frames -=
2665 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2666
Eric Laurent949a0892013-09-20 09:20:13 -07002667 // It would be unusual for this value to be negative, but check just in case ...
2668 if (signed_frames >= 0) {
2669 *frames = signed_frames;
2670 ret = 0;
2671 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002672 }
2673 }
2674 }
2675
2676 pthread_mutex_unlock(&out->lock);
2677
2678 return ret;
2679}
2680
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002681static int out_set_callback(struct audio_stream_out *stream,
2682 stream_callback_t callback, void *cookie)
2683{
2684 struct stream_out *out = (struct stream_out *)stream;
2685
2686 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002687 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002688 out->offload_callback = callback;
2689 out->offload_cookie = cookie;
2690 pthread_mutex_unlock(&out->lock);
2691 return 0;
2692}
2693
2694static int out_pause(struct audio_stream_out* stream)
2695{
2696 struct stream_out *out = (struct stream_out *)stream;
2697 int status = -ENOSYS;
2698 ALOGV("%s", __func__);
2699 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002700 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002701 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2702 status = compress_pause(out->compr);
2703 out->offload_state = OFFLOAD_STATE_PAUSED;
2704 }
2705 pthread_mutex_unlock(&out->lock);
2706 }
2707 return status;
2708}
2709
2710static int out_resume(struct audio_stream_out* stream)
2711{
2712 struct stream_out *out = (struct stream_out *)stream;
2713 int status = -ENOSYS;
2714 ALOGV("%s", __func__);
2715 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2716 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002717 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002718 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2719 status = compress_resume(out->compr);
2720 out->offload_state = OFFLOAD_STATE_PLAYING;
2721 }
2722 pthread_mutex_unlock(&out->lock);
2723 }
2724 return status;
2725}
2726
2727static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2728{
2729 struct stream_out *out = (struct stream_out *)stream;
2730 int status = -ENOSYS;
2731 ALOGV("%s", __func__);
2732 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002733 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002734 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2735 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2736 else
2737 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2738 pthread_mutex_unlock(&out->lock);
2739 }
2740 return status;
2741}
2742
2743static int out_flush(struct audio_stream_out* stream)
2744{
2745 struct stream_out *out = (struct stream_out *)stream;
2746 ALOGV("%s", __func__);
2747 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002748 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002749 stop_compressed_output_l(out);
2750 pthread_mutex_unlock(&out->lock);
2751 return 0;
2752 }
2753 return -ENOSYS;
2754}
2755
Eric Laurent0e46adf2016-12-16 12:49:24 -08002756static int out_stop(const struct audio_stream_out* stream)
2757{
2758 struct stream_out *out = (struct stream_out *)stream;
2759 struct audio_device *adev = out->dev;
2760 int ret = -ENOSYS;
2761
2762 ALOGV("%s", __func__);
2763 pthread_mutex_lock(&adev->lock);
2764 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2765 out->playback_started && out->pcm != NULL) {
2766 pcm_stop(out->pcm);
2767 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002768 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002769 }
2770 pthread_mutex_unlock(&adev->lock);
2771 return ret;
2772}
2773
2774static int out_start(const struct audio_stream_out* stream)
2775{
2776 struct stream_out *out = (struct stream_out *)stream;
2777 struct audio_device *adev = out->dev;
2778 int ret = -ENOSYS;
2779
2780 ALOGV("%s", __func__);
2781 pthread_mutex_lock(&adev->lock);
2782 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2783 !out->playback_started && out->pcm != NULL) {
2784 ret = start_output_stream(out);
2785 if (ret == 0) {
2786 out->playback_started = true;
2787 }
2788 }
2789 pthread_mutex_unlock(&adev->lock);
2790 return ret;
2791}
2792
Phil Burkbc991042017-02-24 08:06:44 -08002793/*
2794 * Modify config->period_count based on min_size_frames
2795 */
2796static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2797{
2798 int periodCountRequested = (min_size_frames + config->period_size - 1)
2799 / config->period_size;
2800 int periodCount = MMAP_PERIOD_COUNT_MIN;
2801
2802 ALOGV("%s original config.period_size = %d config.period_count = %d",
2803 __func__, config->period_size, config->period_count);
2804
2805 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2806 periodCount *= 2;
2807 }
2808 config->period_count = periodCount;
2809
2810 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2811}
2812
Eric Laurent0e46adf2016-12-16 12:49:24 -08002813static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2814 int32_t min_size_frames,
2815 struct audio_mmap_buffer_info *info)
2816{
2817 struct stream_out *out = (struct stream_out *)stream;
2818 struct audio_device *adev = out->dev;
2819 int ret = 0;
2820 unsigned int offset1;
2821 unsigned int frames1;
2822 const char *step = "";
2823
2824 ALOGV("%s", __func__);
2825 pthread_mutex_lock(&adev->lock);
2826
2827 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002828 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002829 ret = -EINVAL;
2830 goto exit;
2831 }
2832 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002833 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002834 ret = -ENOSYS;
2835 goto exit;
2836 }
2837 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2838 if (out->pcm_device_id < 0) {
2839 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2840 __func__, out->pcm_device_id, out->usecase);
2841 ret = -EINVAL;
2842 goto exit;
2843 }
Phil Burkbc991042017-02-24 08:06:44 -08002844
2845 adjust_mmap_period_count(&out->config, min_size_frames);
2846
Eric Laurent0e46adf2016-12-16 12:49:24 -08002847 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2848 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2849 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2850 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2851 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2852 step = "open";
2853 ret = -ENODEV;
2854 goto exit;
2855 }
2856 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2857 if (ret < 0) {
2858 step = "begin";
2859 goto exit;
2860 }
2861 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2862 info->burst_size_frames = out->config.period_size;
2863 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2864
2865 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2866 info->buffer_size_frames));
2867
2868 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2869 if (ret < 0) {
2870 step = "commit";
2871 goto exit;
2872 }
Phil Burkbc991042017-02-24 08:06:44 -08002873
2874 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002875 ret = 0;
2876
2877 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2878 __func__, info->shared_memory_address, info->buffer_size_frames);
2879
2880exit:
2881 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002882 if (out->pcm == NULL) {
2883 ALOGE("%s: %s - %d", __func__, step, ret);
2884 } else {
2885 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002886 pcm_close(out->pcm);
2887 out->pcm = NULL;
2888 }
2889 }
2890 pthread_mutex_unlock(&adev->lock);
2891 return ret;
2892}
2893
2894static int out_get_mmap_position(const struct audio_stream_out *stream,
2895 struct audio_mmap_position *position)
2896{
2897 struct stream_out *out = (struct stream_out *)stream;
2898 ALOGVV("%s", __func__);
2899 if (position == NULL) {
2900 return -EINVAL;
2901 }
2902 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2903 return -ENOSYS;
2904 }
2905 if (out->pcm == NULL) {
2906 return -ENOSYS;
2907 }
2908
2909 struct timespec ts = { 0, 0 };
2910 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2911 if (ret < 0) {
2912 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2913 return ret;
2914 }
Andy Hungfc044e12017-03-20 09:24:22 -07002915 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002916 return 0;
2917}
2918
2919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920/** audio_stream_in implementation **/
2921static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2922{
2923 struct stream_in *in = (struct stream_in *)stream;
2924
2925 return in->config.rate;
2926}
2927
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002928static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929{
2930 return -ENOSYS;
2931}
2932
2933static size_t in_get_buffer_size(const struct audio_stream *stream)
2934{
2935 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002936 return in->config.period_size * in->af_period_multiplier *
2937 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938}
2939
2940static uint32_t in_get_channels(const struct audio_stream *stream)
2941{
2942 struct stream_in *in = (struct stream_in *)stream;
2943
2944 return in->channel_mask;
2945}
2946
vivek mehta4ed66e62016-04-15 23:33:34 -07002947static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002948{
vivek mehta4ed66e62016-04-15 23:33:34 -07002949 struct stream_in *in = (struct stream_in *)stream;
2950 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951}
2952
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002953static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954{
2955 return -ENOSYS;
2956}
2957
2958static int in_standby(struct audio_stream *stream)
2959{
2960 struct stream_in *in = (struct stream_in *)stream;
2961 struct audio_device *adev = in->dev;
2962 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002963 bool do_stop = true;
2964
Eric Laurent994a6932013-07-17 11:51:42 -07002965 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002966
2967 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002968
2969 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002970 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002971 audio_extn_sound_trigger_stop_lab(in);
2972 in->standby = true;
2973 }
2974
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002976 if (adev->adm_deregister_stream)
2977 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2978
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002979 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002981 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002982 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002983 in->capture_started = false;
2984 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002985 if (in->pcm) {
2986 pcm_close(in->pcm);
2987 in->pcm = NULL;
2988 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002989 adev->enable_voicerx = false;
2990 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002991 if (do_stop) {
2992 status = stop_input_stream(in);
2993 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002994 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995 }
2996 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002997 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 return status;
2999}
3000
Andy Hungd13f0d32017-06-12 13:58:37 -07003001static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002{
Andy Hungd13f0d32017-06-12 13:58:37 -07003003 struct stream_in *in = (struct stream_in *)stream;
3004
3005 // We try to get the lock for consistency,
3006 // but it isn't necessary for these variables.
3007 // If we're not in standby, we may be blocked on a read.
3008 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3009 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3010 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3011 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3012
3013 if (locked) {
3014 pthread_mutex_unlock(&in->lock);
3015 }
3016
3017 // dump error info
3018 (void)error_log_dump(
3019 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 return 0;
3021}
3022
3023static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3024{
3025 struct stream_in *in = (struct stream_in *)stream;
3026 struct audio_device *adev = in->dev;
3027 struct str_parms *parms;
3028 char *str;
3029 char value[32];
3030 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003031 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032
Eric Laurent994a6932013-07-17 11:51:42 -07003033 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003034 parms = str_parms_create_str(kvpairs);
3035
3036 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3037
Eric Laurenta1478072015-09-21 17:21:52 -07003038 lock_input_stream(in);
3039
Eric Laurent150dbfe2013-02-27 14:31:02 -08003040 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 if (ret >= 0) {
3042 val = atoi(value);
3043 /* no audio source uses val == 0 */
3044 if ((in->source != val) && (val != 0)) {
3045 in->source = val;
3046 }
3047 }
3048
3049 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003050
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 if (ret >= 0) {
3052 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003053 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003054 in->device = val;
3055 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003056 if (!in->standby) {
3057 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003058 // inform adm before actual routing to prevent glitches.
3059 if (adev->adm_on_routing_change) {
3060 adev->adm_on_routing_change(adev->adm_data,
3061 in->capture_handle);
3062 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003063 select_devices(adev, in->usecase);
3064 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 }
3066 }
3067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003069 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070
3071 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003072 ALOGV("%s: exit: status(%d)", __func__, status);
3073 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074}
3075
Haynes Mathew George569b7482017-05-08 14:44:27 -07003076static char* in_get_parameters(const struct audio_stream *stream,
3077 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003079 struct stream_in *in = (struct stream_in *)stream;
3080 struct str_parms *query = str_parms_create_str(keys);
3081 char *str;
3082 struct str_parms *reply = str_parms_create();
3083 bool replied = false;
3084
3085 ALOGV("%s: enter: keys - %s", __func__, keys);
3086 replied |= stream_get_parameter_channels(query, reply,
3087 &in->supported_channel_masks[0]);
3088 replied |= stream_get_parameter_formats(query, reply,
3089 &in->supported_formats[0]);
3090 replied |= stream_get_parameter_rates(query, reply,
3091 &in->supported_sample_rates[0]);
3092 if (replied) {
3093 str = str_parms_to_str(reply);
3094 } else {
3095 str = strdup(keys);
3096 }
3097 str_parms_destroy(query);
3098 str_parms_destroy(reply);
3099 ALOGV("%s: exit: returns - %s", __func__, str);
3100 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101}
3102
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003103static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003105 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106}
3107
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003108static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3109{
3110 if (!stream || !parms)
3111 return;
3112
3113 struct stream_in *in = (struct stream_in *)stream;
3114 struct audio_device *adev = in->dev;
3115
3116 card_status_t status;
3117 int card;
3118 if (parse_snd_card_status(parms, &card, &status) < 0)
3119 return;
3120
3121 pthread_mutex_lock(&adev->lock);
3122 bool valid_cb = (card == adev->snd_card);
3123 pthread_mutex_unlock(&adev->lock);
3124
3125 if (!valid_cb)
3126 return;
3127
3128 lock_input_stream(in);
3129 if (in->card_status != status)
3130 in->card_status = status;
3131 pthread_mutex_unlock(&in->lock);
3132
3133 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3134 use_case_table[in->usecase],
3135 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3136
3137 // a better solution would be to report error back to AF and let
3138 // it put the stream to standby
3139 if (status == CARD_STATUS_OFFLINE)
3140 in_standby(&in->stream.common);
3141
3142 return;
3143}
3144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3146 size_t bytes)
3147{
3148 struct stream_in *in = (struct stream_in *)stream;
3149 struct audio_device *adev = in->dev;
3150 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003151 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003152 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153
Eric Laurenta1478072015-09-21 17:21:52 -07003154 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003155 const size_t frame_size = audio_stream_in_frame_size(stream);
3156 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003157
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003158 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003159 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003160 /* Read from sound trigger HAL */
3161 audio_extn_sound_trigger_read(in, buffer, bytes);
3162 pthread_mutex_unlock(&in->lock);
3163 return bytes;
3164 }
3165
Eric Laurent0e46adf2016-12-16 12:49:24 -08003166 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3167 ret = -ENOSYS;
3168 goto exit;
3169 }
3170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003172 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003173 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003174 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176 goto exit;
3177 }
3178 in->standby = 0;
3179 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180
Andy Hungd13f0d32017-06-12 13:58:37 -07003181 // errors that occur here are read errors.
3182 error_code = ERROR_CODE_READ;
3183
Haynes Mathew George03c40102016-01-29 17:57:48 -08003184 //what's the duration requested by the client?
3185 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3186 in->config.rate;
3187 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003188
Haynes Mathew George03c40102016-01-29 17:57:48 -08003189 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003191 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003192 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003193 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003194 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003195 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003196 if (ret < 0) {
3197 ALOGE("Failed to read w/err %s", strerror(errno));
3198 ret = -errno;
3199 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003200 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3201 if (bytes % 4 == 0) {
3202 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3203 int_buf_stream = buffer;
3204 for (size_t itt=0; itt < bytes/4 ; itt++) {
3205 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003206 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003207 } else {
3208 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3209 ret = -EINVAL;
3210 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003211 }
3212 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 }
3214
Haynes Mathew George03c40102016-01-29 17:57:48 -08003215 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 /*
3218 * Instead of writing zeroes here, we could trust the hardware
3219 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003220 * 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 -08003221 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003222 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003224 in->frames_muted += frames;
3225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226
3227exit:
3228 pthread_mutex_unlock(&in->lock);
3229
3230 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003231 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 in_standby(&in->stream.common);
3233 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003234 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003235 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003236 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003237 }
3238 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003239 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240 }
3241 return bytes;
3242}
3243
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003244static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003245{
3246 return 0;
3247}
3248
Andy Hung6ebe5962016-01-15 17:46:57 -08003249static int in_get_capture_position(const struct audio_stream_in *stream,
3250 int64_t *frames, int64_t *time)
3251{
3252 if (stream == NULL || frames == NULL || time == NULL) {
3253 return -EINVAL;
3254 }
3255 struct stream_in *in = (struct stream_in *)stream;
3256 int ret = -ENOSYS;
3257
3258 lock_input_stream(in);
3259 if (in->pcm) {
3260 struct timespec timestamp;
3261 unsigned int avail;
3262 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3263 *frames = in->frames_read + avail;
3264 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3265 ret = 0;
3266 }
3267 }
3268 pthread_mutex_unlock(&in->lock);
3269 return ret;
3270}
3271
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003272static int add_remove_audio_effect(const struct audio_stream *stream,
3273 effect_handle_t effect,
3274 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003276 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003277 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003278 int status = 0;
3279 effect_descriptor_t desc;
3280
3281 status = (*effect)->get_descriptor(effect, &desc);
3282 if (status != 0)
3283 return status;
3284
Eric Laurenta1478072015-09-21 17:21:52 -07003285 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003286 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003287 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003288 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003289 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003290 in->enable_aec != enable &&
3291 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3292 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003293 if (!enable)
3294 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003295 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3296 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3297 adev->enable_voicerx = enable;
3298 struct audio_usecase *usecase;
3299 struct listnode *node;
3300 list_for_each(node, &adev->usecase_list) {
3301 usecase = node_to_item(node, struct audio_usecase, list);
3302 if (usecase->type == PCM_PLAYBACK) {
3303 select_devices(adev, usecase->id);
3304 break;
3305 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003306 }
3307 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003308 if (!in->standby)
3309 select_devices(in->dev, in->usecase);
3310 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003311 if (in->enable_ns != enable &&
3312 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3313 in->enable_ns = enable;
3314 if (!in->standby)
3315 select_devices(in->dev, in->usecase);
3316 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003317 pthread_mutex_unlock(&in->dev->lock);
3318 pthread_mutex_unlock(&in->lock);
3319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320 return 0;
3321}
3322
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003323static int in_add_audio_effect(const struct audio_stream *stream,
3324 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325{
Eric Laurent994a6932013-07-17 11:51:42 -07003326 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003327 return add_remove_audio_effect(stream, effect, true);
3328}
3329
3330static int in_remove_audio_effect(const struct audio_stream *stream,
3331 effect_handle_t effect)
3332{
Eric Laurent994a6932013-07-17 11:51:42 -07003333 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003334 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335}
3336
Eric Laurent0e46adf2016-12-16 12:49:24 -08003337static int in_stop(const struct audio_stream_in* stream)
3338{
3339 struct stream_in *in = (struct stream_in *)stream;
3340 struct audio_device *adev = in->dev;
3341
3342 int ret = -ENOSYS;
3343 ALOGV("%s", __func__);
3344 pthread_mutex_lock(&adev->lock);
3345 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3346 in->capture_started && in->pcm != NULL) {
3347 pcm_stop(in->pcm);
3348 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003349 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003350 }
3351 pthread_mutex_unlock(&adev->lock);
3352 return ret;
3353}
3354
3355static int in_start(const struct audio_stream_in* stream)
3356{
3357 struct stream_in *in = (struct stream_in *)stream;
3358 struct audio_device *adev = in->dev;
3359 int ret = -ENOSYS;
3360
3361 ALOGV("%s in %p", __func__, in);
3362 pthread_mutex_lock(&adev->lock);
3363 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3364 !in->capture_started && in->pcm != NULL) {
3365 if (!in->capture_started) {
3366 ret = start_input_stream(in);
3367 if (ret == 0) {
3368 in->capture_started = true;
3369 }
3370 }
3371 }
3372 pthread_mutex_unlock(&adev->lock);
3373 return ret;
3374}
3375
3376static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3377 int32_t min_size_frames,
3378 struct audio_mmap_buffer_info *info)
3379{
3380 struct stream_in *in = (struct stream_in *)stream;
3381 struct audio_device *adev = in->dev;
3382 int ret = 0;
3383 unsigned int offset1;
3384 unsigned int frames1;
3385 const char *step = "";
3386
3387 pthread_mutex_lock(&adev->lock);
3388 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003389
Eric Laurent0e46adf2016-12-16 12:49:24 -08003390 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003391 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003392 ret = -EINVAL;
3393 goto exit;
3394 }
3395 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003396 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003397 ALOGV("%s in %p", __func__, in);
3398 ret = -ENOSYS;
3399 goto exit;
3400 }
3401 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3402 if (in->pcm_device_id < 0) {
3403 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3404 __func__, in->pcm_device_id, in->usecase);
3405 ret = -EINVAL;
3406 goto exit;
3407 }
Phil Burkbc991042017-02-24 08:06:44 -08003408
3409 adjust_mmap_period_count(&in->config, min_size_frames);
3410
Eric Laurent0e46adf2016-12-16 12:49:24 -08003411 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3412 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3413 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3414 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3415 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3416 step = "open";
3417 ret = -ENODEV;
3418 goto exit;
3419 }
3420
3421 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3422 if (ret < 0) {
3423 step = "begin";
3424 goto exit;
3425 }
3426 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3427 info->burst_size_frames = in->config.period_size;
3428 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3429
3430 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3431 info->buffer_size_frames));
3432
3433 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3434 if (ret < 0) {
3435 step = "commit";
3436 goto exit;
3437 }
3438
Phil Burkbc991042017-02-24 08:06:44 -08003439 in->standby = false;
3440 ret = 0;
3441
Eric Laurent0e46adf2016-12-16 12:49:24 -08003442 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3443 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003444
3445exit:
3446 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003447 if (in->pcm == NULL) {
3448 ALOGE("%s: %s - %d", __func__, step, ret);
3449 } else {
3450 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003451 pcm_close(in->pcm);
3452 in->pcm = NULL;
3453 }
3454 }
3455 pthread_mutex_unlock(&adev->lock);
3456 return ret;
3457}
3458
3459static int in_get_mmap_position(const struct audio_stream_in *stream,
3460 struct audio_mmap_position *position)
3461{
3462 struct stream_in *in = (struct stream_in *)stream;
3463 ALOGVV("%s", __func__);
3464 if (position == NULL) {
3465 return -EINVAL;
3466 }
3467 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3468 return -ENOSYS;
3469 }
3470 if (in->pcm == NULL) {
3471 return -ENOSYS;
3472 }
3473 struct timespec ts = { 0, 0 };
3474 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3475 if (ret < 0) {
3476 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3477 return ret;
3478 }
Andy Hungfc044e12017-03-20 09:24:22 -07003479 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003480 return 0;
3481}
3482
3483
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484static int adev_open_output_stream(struct audio_hw_device *dev,
3485 audio_io_handle_t handle,
3486 audio_devices_t devices,
3487 audio_output_flags_t flags,
3488 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003489 struct audio_stream_out **stream_out,
3490 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003491{
3492 struct audio_device *adev = (struct audio_device *)dev;
3493 struct stream_out *out;
3494 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003495 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3496 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3497 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3498 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499
Eric Laurent994a6932013-07-17 11:51:42 -07003500 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003501 __func__, config->sample_rate, config->channel_mask, devices, flags);
3502 *stream_out = NULL;
3503 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3504
3505 if (devices == AUDIO_DEVICE_NONE)
3506 devices = AUDIO_DEVICE_OUT_SPEAKER;
3507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508 out->flags = flags;
3509 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003510 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003511 out->format = config->format;
3512 out->sample_rate = config->sample_rate;
3513 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3514 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003515 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516
3517 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003518 if (audio_is_linear_pcm(out->format) &&
3519 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003520 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003521 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003522 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003523 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003524 if (config->sample_rate == 0)
3525 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3526 if (config->channel_mask == 0)
3527 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3528 if (config->format == AUDIO_FORMAT_DEFAULT)
3529 config->format = AUDIO_FORMAT_PCM_16_BIT;
3530 } else if (is_usb_dev) {
3531 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3532 &config->format,
3533 &out->supported_formats[0],
3534 MAX_SUPPORTED_FORMATS,
3535 &config->channel_mask,
3536 &out->supported_channel_masks[0],
3537 MAX_SUPPORTED_CHANNEL_MASKS,
3538 &config->sample_rate,
3539 &out->supported_sample_rates[0],
3540 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003541 ALOGV("plugged dev USB ret %d", ret);
3542 } else {
3543 ret = -1;
3544 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003545 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003546 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003547 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003548
Haynes Mathew George569b7482017-05-08 14:44:27 -07003549 out->channel_mask = config->channel_mask;
3550 out->sample_rate = config->sample_rate;
3551 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003552 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3553 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003554 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003556 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003558 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003559 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003560 pthread_mutex_lock(&adev->lock);
3561 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3562 pthread_mutex_unlock(&adev->lock);
3563
3564 // reject offload during card offline to allow
3565 // fallback to s/w paths
3566 if (offline) {
3567 ret = -ENODEV;
3568 goto error_open;
3569 }
3570
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003571 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3572 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3573 ALOGE("%s: Unsupported Offload information", __func__);
3574 ret = -EINVAL;
3575 goto error_open;
3576 }
3577 if (!is_supported_format(config->offload_info.format)) {
3578 ALOGE("%s: Unsupported audio format", __func__);
3579 ret = -EINVAL;
3580 goto error_open;
3581 }
3582
3583 out->compr_config.codec = (struct snd_codec *)
3584 calloc(1, sizeof(struct snd_codec));
3585
3586 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3587 if (config->offload_info.channel_mask)
3588 out->channel_mask = config->offload_info.channel_mask;
3589 else if (config->channel_mask)
3590 out->channel_mask = config->channel_mask;
3591 out->format = config->offload_info.format;
3592 out->sample_rate = config->offload_info.sample_rate;
3593
3594 out->stream.set_callback = out_set_callback;
3595 out->stream.pause = out_pause;
3596 out->stream.resume = out_resume;
3597 out->stream.drain = out_drain;
3598 out->stream.flush = out_flush;
3599
3600 out->compr_config.codec->id =
3601 get_snd_codec_id(config->offload_info.format);
3602 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3603 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003604 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003605 out->compr_config.codec->bit_rate =
3606 config->offload_info.bit_rate;
3607 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003608 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003609 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3610
3611 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3612 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003613
3614 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003615 create_offload_callback_thread(out);
3616 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3617 __func__, config->offload_info.version,
3618 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003619 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003620 switch (config->sample_rate) {
3621 case 8000:
3622 case 16000:
3623 case 48000:
3624 out->sample_rate = config->sample_rate;
3625 break;
3626 default:
3627 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003628 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003629 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003630 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3631 out->config = pcm_config_afe_proxy_playback;
3632 adev->voice_tx_output = out;
vivek mehtaa68fea62017-06-08 19:04:02 -07003633 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3634 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3635 AUDIO_OUTPUT_FLAG_VOIP_RX))) {
3636 uint32_t buffer_size, frame_size;
3637 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3638 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3639 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3640 out->config = pcm_config_voip;
3641 out->config.format = pcm_format_from_audio_format(config->format);
3642 out->config.rate = config->sample_rate;
3643 out->config.channels =
3644 audio_channel_count_from_out_mask(config->channel_mask);
3645 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3646 config->sample_rate,
3647 config->format,
3648 out->config.channels,
3649 false /*is_low_latency*/);
3650 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3651 out->config.period_size = buffer_size / frame_size;
3652 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3653 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003654 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003655 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3656 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3657 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003658 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3659 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3660 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003661 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3662 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003663 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003664 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003665 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3666 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3667 out->config = pcm_config_mmap_playback;
3668 out->stream.start = out_start;
3669 out->stream.stop = out_stop;
3670 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3671 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003672 } else {
3673 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3674 out->config = pcm_config_low_latency;
3675 }
3676 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3677 if (k_enable_extended_precision
3678 && pcm_params_format_test(adev->use_case_table[out->usecase],
3679 pcm_format_from_audio_format(config->format))) {
3680 out->config.format = pcm_format_from_audio_format(config->format);
3681 /* out->format already set to config->format */
3682 } else {
3683 /* deny the externally proposed config format
3684 * and use the one specified in audio_hw layer configuration.
3685 * Note: out->format is returned by out->stream.common.get_format()
3686 * and is used to set config->format in the code several lines below.
3687 */
3688 out->format = audio_format_from_pcm_format(out->config.format);
3689 }
3690 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003691 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003693
3694 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3695 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3696 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3697 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3698 __func__, config->sample_rate, config->format, config->channel_mask);
3699 config->sample_rate = out->sample_rate;
3700 config->format = out->format;
3701 config->channel_mask = out->channel_mask;
3702 ret = -EINVAL;
3703 goto error_open;
3704 }
3705
Andy Hung6fcba9c2014-03-18 11:53:32 -07003706 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3707 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003709 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003710 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003711 adev->primary_output = out;
3712 else {
3713 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003714 ret = -EEXIST;
3715 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003716 }
3717 }
3718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 /* Check if this usecase is already existing */
3720 pthread_mutex_lock(&adev->lock);
3721 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3722 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003723 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003724 ret = -EEXIST;
3725 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003726 }
3727 pthread_mutex_unlock(&adev->lock);
3728
3729 out->stream.common.get_sample_rate = out_get_sample_rate;
3730 out->stream.common.set_sample_rate = out_set_sample_rate;
3731 out->stream.common.get_buffer_size = out_get_buffer_size;
3732 out->stream.common.get_channels = out_get_channels;
3733 out->stream.common.get_format = out_get_format;
3734 out->stream.common.set_format = out_set_format;
3735 out->stream.common.standby = out_standby;
3736 out->stream.common.dump = out_dump;
3737 out->stream.common.set_parameters = out_set_parameters;
3738 out->stream.common.get_parameters = out_get_parameters;
3739 out->stream.common.add_audio_effect = out_add_audio_effect;
3740 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3741 out->stream.get_latency = out_get_latency;
3742 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003743#ifdef NO_AUDIO_OUT
3744 out->stream.write = out_write_for_no_output;
3745#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003747#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 out->stream.get_render_position = out_get_render_position;
3749 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003750 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003751
Eric Laurent0e46adf2016-12-16 12:49:24 -08003752 if (out->realtime)
3753 out->af_period_multiplier = af_period_multiplier;
3754 else
3755 out->af_period_multiplier = 1;
3756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003758 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003759 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003761 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003762 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003763 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 config->format = out->stream.common.get_format(&out->stream.common);
3766 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3767 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3768
Andy Hunga452b0a2017-03-15 14:51:15 -07003769 out->error_log = error_log_create(
3770 ERROR_LOG_ENTRIES,
3771 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3772
Andy Hungfc044e12017-03-20 09:24:22 -07003773 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003774 // or not a userdebug or eng build.
Andy Hunge12f7302017-06-07 15:07:37 -07003775 if (is_userdebug_or_eng_build()) {
Andy Hung9e737de2017-05-22 10:51:22 -07003776 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3777 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3778
3779 out->power_log = power_log_create(
3780 config->sample_rate,
3781 audio_channel_count_from_out_mask(config->channel_mask),
3782 config->format,
3783 POWER_LOG_ENTRIES,
3784 POWER_LOG_FRAMES_PER_ENTRY);
3785 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003786
3787 /*
3788 By locking output stream before registering, we allow the callback
3789 to update stream's state only after stream's initial state is set to
3790 adev state.
3791 */
3792 lock_output_stream(out);
3793 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3794 pthread_mutex_lock(&adev->lock);
3795 out->card_status = adev->card_status;
3796 pthread_mutex_unlock(&adev->lock);
3797 pthread_mutex_unlock(&out->lock);
3798
vivek mehta4a824772017-06-08 19:05:49 -07003799 stream_app_type_cfg_init(&out->app_type_cfg);
3800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003802
Eric Laurent994a6932013-07-17 11:51:42 -07003803 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003805
3806error_open:
3807 free(out);
3808 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003809 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003810 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811}
3812
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003813static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814 struct audio_stream_out *stream)
3815{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003816 struct stream_out *out = (struct stream_out *)stream;
3817 struct audio_device *adev = out->dev;
3818
Eric Laurent994a6932013-07-17 11:51:42 -07003819 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003820
3821 // must deregister from sndmonitor first to prevent races
3822 // between the callback and close_stream
3823 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003825 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3826 destroy_offload_callback_thread(out);
3827
3828 if (out->compr_config.codec != NULL)
3829 free(out->compr_config.codec);
3830 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003831
3832 if (adev->voice_tx_output == out)
3833 adev->voice_tx_output = NULL;
3834
Andy Hungfc044e12017-03-20 09:24:22 -07003835 power_log_destroy(out->power_log);
3836 out->power_log = NULL;
3837
Andy Hunga452b0a2017-03-15 14:51:15 -07003838 error_log_destroy(out->error_log);
3839 out->error_log = NULL;
3840
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003841 pthread_cond_destroy(&out->cond);
3842 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003844 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845}
3846
3847static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3848{
3849 struct audio_device *adev = (struct audio_device *)dev;
3850 struct str_parms *parms;
3851 char *str;
3852 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003853 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003854 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003855 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856
Joe Onorato188b6222016-03-01 11:02:27 -08003857 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003858
3859 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860
3861 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003862 status = voice_set_parameters(adev, parms);
3863 if (status != 0) {
3864 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865 }
3866
3867 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3868 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003869 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3871 adev->bluetooth_nrec = true;
3872 else
3873 adev->bluetooth_nrec = false;
3874 }
3875
3876 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3877 if (ret >= 0) {
3878 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3879 adev->screen_off = false;
3880 else
3881 adev->screen_off = true;
3882 }
3883
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003884 ret = str_parms_get_int(parms, "rotation", &val);
3885 if (ret >= 0) {
3886 bool reverse_speakers = false;
3887 switch(val) {
3888 // FIXME: note that the code below assumes that the speakers are in the correct placement
3889 // relative to the user when the device is rotated 90deg from its default rotation. This
3890 // assumption is device-specific, not platform-specific like this code.
3891 case 270:
3892 reverse_speakers = true;
3893 break;
3894 case 0:
3895 case 90:
3896 case 180:
3897 break;
3898 default:
3899 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003900 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003901 }
Eric Laurent03f09432014-03-25 18:09:11 -07003902 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003903 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003904 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003905 }
3906
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003907 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3908 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003909 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003910 }
3911
David Linee3fe402017-03-13 10:00:42 -07003912 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3913 if (ret >= 0) {
3914 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3915 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3916 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3917 if (ret >= 0) {
3918 const int card = atoi(value);
3919 audio_extn_usb_add_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3920 }
3921 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3922 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3923 if (ret >= 0) {
3924 const int card = atoi(value);
3925 audio_extn_usb_add_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3926 }
3927 }
3928 }
3929
3930 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3931 if (ret >= 0) {
3932 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
3933 if (device == AUDIO_DEVICE_OUT_USB_DEVICE) {
3934 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3935 if (ret >= 0) {
3936 const int card = atoi(value);
3937
3938 audio_extn_usb_remove_device(AUDIO_DEVICE_OUT_USB_DEVICE, card);
3939 }
3940 } else if (device == AUDIO_DEVICE_IN_USB_DEVICE) {
3941 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3942 if (ret >= 0) {
3943 const int card = atoi(value);
3944 audio_extn_usb_remove_device(AUDIO_DEVICE_IN_USB_DEVICE, card);
3945 }
3946 }
3947 }
3948
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003949 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003950done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003952 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003953 ALOGV("%s: exit with code(%d)", __func__, status);
3954 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003955}
3956
3957static char* adev_get_parameters(const struct audio_hw_device *dev,
3958 const char *keys)
3959{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003960 struct audio_device *adev = (struct audio_device *)dev;
3961 struct str_parms *reply = str_parms_create();
3962 struct str_parms *query = str_parms_create_str(keys);
3963 char *str;
3964
3965 pthread_mutex_lock(&adev->lock);
3966
3967 voice_get_parameters(adev, query, reply);
3968 str = str_parms_to_str(reply);
3969 str_parms_destroy(query);
3970 str_parms_destroy(reply);
3971
3972 pthread_mutex_unlock(&adev->lock);
3973 ALOGV("%s: exit: returns - %s", __func__, str);
3974 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003975}
3976
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003977static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978{
3979 return 0;
3980}
3981
Haynes Mathew George5191a852013-09-11 14:19:36 -07003982static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3983{
3984 int ret;
3985 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003986
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003987 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3988
Haynes Mathew George5191a852013-09-11 14:19:36 -07003989 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003990 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003991 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003992
Haynes Mathew George5191a852013-09-11 14:19:36 -07003993 return ret;
3994}
3995
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003996static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003997{
3998 return -ENOSYS;
3999}
4000
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004001static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4002 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004003{
4004 return -ENOSYS;
4005}
4006
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004007static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008{
4009 return -ENOSYS;
4010}
4011
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004012static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004013{
4014 return -ENOSYS;
4015}
4016
4017static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4018{
4019 struct audio_device *adev = (struct audio_device *)dev;
4020
4021 pthread_mutex_lock(&adev->lock);
4022 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004023 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004025 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4026 voice_is_in_call(adev)) {
4027 voice_stop_call(adev);
4028 adev->current_call_output = NULL;
4029 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004030 }
4031 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004032
4033 audio_extn_extspk_set_mode(adev->extspk, mode);
4034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035 return 0;
4036}
4037
4038static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4039{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004040 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042
Eric Laurent2bafff12016-03-17 12:17:23 -07004043 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004044 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004045 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4046 ret = audio_extn_hfp_set_mic_mute(adev, state);
4047 } else {
4048 ret = voice_set_mic_mute(adev, state);
4049 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004050 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004051 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004052
4053 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054}
4055
4056static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4057{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004058 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004059 return 0;
4060}
4061
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004062static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004063 const struct audio_config *config)
4064{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004065 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004066
vivek mehtaa68fea62017-06-08 19:04:02 -07004067 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4068 config->sample_rate, config->format,
4069 channel_count,
4070 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071}
4072
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004073static bool adev_input_allow_hifi_record(struct audio_device *adev,
4074 audio_devices_t devices,
4075 audio_input_flags_t flags,
4076 audio_source_t source) {
4077 const bool allowed = true;
4078
4079 if (!audio_is_usb_in_device(devices))
4080 return !allowed;
4081
4082 switch (flags) {
4083 case AUDIO_INPUT_FLAG_NONE:
4084 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4085 break;
4086 default:
4087 return !allowed;
4088 }
4089
4090 switch (source) {
4091 case AUDIO_SOURCE_DEFAULT:
4092 case AUDIO_SOURCE_MIC:
4093 case AUDIO_SOURCE_UNPROCESSED:
4094 break;
4095 default:
4096 return !allowed;
4097 }
4098
4099 switch (adev->mode) {
4100 case 0:
4101 break;
4102 default:
4103 return !allowed;
4104 }
4105
4106 return allowed;
4107}
4108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004110 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111 audio_devices_t devices,
4112 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004113 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004114 audio_input_flags_t flags,
4115 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004116 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004117{
4118 struct audio_device *adev = (struct audio_device *)dev;
4119 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004120 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004121 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004122 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004123 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004124 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4125 devices,
4126 flags,
4127 source);
4128 ALOGE("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004130
4131 if (config->sample_rate == 0)
4132 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4133 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4134 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4135 if (config->format == AUDIO_FORMAT_DEFAULT)
4136 config->format = AUDIO_FORMAT_PCM_16_BIT;
4137
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
4139 return -EINVAL;
4140
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004141 if (audio_extn_tfa_98xx_is_supported() &&
4142 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004143 return -EINVAL;
4144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4146
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004147 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004148 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150 in->stream.common.get_sample_rate = in_get_sample_rate;
4151 in->stream.common.set_sample_rate = in_set_sample_rate;
4152 in->stream.common.get_buffer_size = in_get_buffer_size;
4153 in->stream.common.get_channels = in_get_channels;
4154 in->stream.common.get_format = in_get_format;
4155 in->stream.common.set_format = in_set_format;
4156 in->stream.common.standby = in_standby;
4157 in->stream.common.dump = in_dump;
4158 in->stream.common.set_parameters = in_set_parameters;
4159 in->stream.common.get_parameters = in_get_parameters;
4160 in->stream.common.add_audio_effect = in_add_audio_effect;
4161 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4162 in->stream.set_gain = in_set_gain;
4163 in->stream.read = in_read;
4164 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004165 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166
4167 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004168 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170 in->standby = 1;
4171 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004172 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004173 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004174
Haynes Mathew George569b7482017-05-08 14:44:27 -07004175 if (is_usb_dev && may_use_hifi_record) {
4176 /* HiFi record selects an appropriate format, channel, rate combo
4177 depending on sink capabilities*/
4178 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4179 &config->format,
4180 &in->supported_formats[0],
4181 MAX_SUPPORTED_FORMATS,
4182 &config->channel_mask,
4183 &in->supported_channel_masks[0],
4184 MAX_SUPPORTED_CHANNEL_MASKS,
4185 &config->sample_rate,
4186 &in->supported_sample_rates[0],
4187 MAX_SUPPORTED_SAMPLE_RATES);
4188 if (ret != 0) {
4189 ret = -EINVAL;
4190 goto err_open;
4191 }
4192 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004193 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004194 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4195 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4196 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4197 bool ret_error = false;
4198 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4199 from HAL is 8_24
4200 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4201 8_24 return error indicating supported format is 8_24
4202 *> In case of any other source requesting 24 bit or float return error
4203 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004204
vivek mehta57ff9b52016-04-28 14:13:08 -07004205 on error flinger will retry with supported format passed
4206 */
4207 if (source != AUDIO_SOURCE_UNPROCESSED) {
4208 config->format = AUDIO_FORMAT_PCM_16_BIT;
4209 ret_error = true;
4210 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4211 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4212 ret_error = true;
4213 }
4214
4215 if (ret_error) {
4216 ret = -EINVAL;
4217 goto err_open;
4218 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004219 }
4220
vivek mehta57ff9b52016-04-28 14:13:08 -07004221 in->format = config->format;
4222
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004224 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4225 if (config->sample_rate == 0)
4226 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4227 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4228 config->sample_rate != 8000) {
4229 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4230 ret = -EINVAL;
4231 goto err_open;
4232 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004233
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004234 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4235 config->format = AUDIO_FORMAT_PCM_16_BIT;
4236 ret = -EINVAL;
4237 goto err_open;
4238 }
4239
4240 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4241 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004242 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004243 } else if (is_usb_dev && may_use_hifi_record) {
4244 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4245 in->config = pcm_config_audio_capture;
4246 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004247 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4248 config->sample_rate,
4249 config->format,
4250 channel_count,
4251 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004252 in->config.period_size = buffer_size / frame_size;
4253 in->config.rate = config->sample_rate;
4254 in->af_period_multiplier = 1;
4255 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004256 } else {
4257 in->usecase = USECASE_AUDIO_RECORD;
4258 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004259 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004260 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004261#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004262 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004263#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004264 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004265 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004266 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004267 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004268 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4269 config->sample_rate,
4270 config->format,
4271 channel_count,
4272 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004273 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004274 in->config.rate = config->sample_rate;
4275 in->af_period_multiplier = 1;
4276 } else {
4277 // period size is left untouched for rt mode playback
4278 in->config = pcm_config_audio_capture_rt;
4279 in->af_period_multiplier = af_period_multiplier;
4280 }
4281 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4282 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004283 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004284 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4285 in->config = pcm_config_mmap_capture;
4286 in->stream.start = in_start;
4287 in->stream.stop = in_stop;
4288 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4289 in->stream.get_mmap_position = in_get_mmap_position;
4290 in->af_period_multiplier = 1;
4291 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004292 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
4293 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004294 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004295 (config->sample_rate == 8000 ||
4296 config->sample_rate == 16000 ||
4297 config->sample_rate == 32000 ||
4298 config->sample_rate == 48000) &&
4299 channel_count == 1) {
4300 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4301 in->config = pcm_config_audio_capture;
4302 frame_size = audio_stream_in_frame_size(&in->stream);
4303 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4304 config->sample_rate,
4305 config->format,
4306 channel_count, false /*is_low_latency*/);
4307 in->config.period_size = buffer_size / frame_size;
4308 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4309 in->config.rate = config->sample_rate;
4310 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004311 } else {
4312 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004313 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004314 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4315 config->sample_rate,
4316 config->format,
4317 channel_count,
4318 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004319 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004320 in->config.rate = config->sample_rate;
4321 in->af_period_multiplier = 1;
4322 }
4323 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4324 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004325 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004328 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329
Andy Hungd13f0d32017-06-12 13:58:37 -07004330 in->error_log = error_log_create(
4331 ERROR_LOG_ENTRIES,
4332 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4333
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004334 /* This stream could be for sound trigger lab,
4335 get sound trigger pcm if present */
4336 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004338 lock_input_stream(in);
4339 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4340 pthread_mutex_lock(&adev->lock);
4341 in->card_status = adev->card_status;
4342 pthread_mutex_unlock(&adev->lock);
4343 pthread_mutex_unlock(&in->lock);
4344
vivek mehta4a824772017-06-08 19:05:49 -07004345 stream_app_type_cfg_init(&in->app_type_cfg);
4346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004348 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349 return 0;
4350
4351err_open:
4352 free(in);
4353 *stream_in = NULL;
4354 return ret;
4355}
4356
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004357static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004358 struct audio_stream_in *stream)
4359{
Andy Hungd13f0d32017-06-12 13:58:37 -07004360 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004361 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004362
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004363 // must deregister from sndmonitor first to prevent races
4364 // between the callback and close_stream
4365 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004366 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004367
4368 error_log_destroy(in->error_log);
4369 in->error_log = NULL;
4370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371 free(stream);
4372
4373 return;
4374}
4375
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004376static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377{
4378 return 0;
4379}
4380
Andy Hung31aca912014-03-20 17:14:59 -07004381/* verifies input and output devices and their capabilities.
4382 *
4383 * This verification is required when enabling extended bit-depth or
4384 * sampling rates, as not all qcom products support it.
4385 *
4386 * Suitable for calling only on initialization such as adev_open().
4387 * It fills the audio_device use_case_table[] array.
4388 *
4389 * Has a side-effect that it needs to configure audio routing / devices
4390 * in order to power up the devices and read the device parameters.
4391 * It does not acquire any hw device lock. Should restore the devices
4392 * back to "normal state" upon completion.
4393 */
4394static int adev_verify_devices(struct audio_device *adev)
4395{
4396 /* enumeration is a bit difficult because one really wants to pull
4397 * the use_case, device id, etc from the hidden pcm_device_table[].
4398 * In this case there are the following use cases and device ids.
4399 *
4400 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4401 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004402 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004403 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4404 * [USECASE_AUDIO_RECORD] = {0, 0},
4405 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4406 * [USECASE_VOICE_CALL] = {2, 2},
4407 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004408 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004409 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4410 */
4411
4412 /* should be the usecases enabled in adev_open_input_stream() */
4413 static const int test_in_usecases[] = {
4414 USECASE_AUDIO_RECORD,
4415 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4416 };
4417 /* should be the usecases enabled in adev_open_output_stream()*/
4418 static const int test_out_usecases[] = {
4419 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4420 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4421 };
4422 static const usecase_type_t usecase_type_by_dir[] = {
4423 PCM_PLAYBACK,
4424 PCM_CAPTURE,
4425 };
4426 static const unsigned flags_by_dir[] = {
4427 PCM_OUT,
4428 PCM_IN,
4429 };
4430
4431 size_t i;
4432 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004433 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004434 char info[512]; /* for possible debug info */
4435
4436 for (dir = 0; dir < 2; ++dir) {
4437 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4438 const unsigned flags_dir = flags_by_dir[dir];
4439 const size_t testsize =
4440 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4441 const int *testcases =
4442 dir ? test_in_usecases : test_out_usecases;
4443 const audio_devices_t audio_device =
4444 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4445
4446 for (i = 0; i < testsize; ++i) {
4447 const audio_usecase_t audio_usecase = testcases[i];
4448 int device_id;
4449 snd_device_t snd_device;
4450 struct pcm_params **pparams;
4451 struct stream_out out;
4452 struct stream_in in;
4453 struct audio_usecase uc_info;
4454 int retval;
4455
4456 pparams = &adev->use_case_table[audio_usecase];
4457 pcm_params_free(*pparams); /* can accept null input */
4458 *pparams = NULL;
4459
4460 /* find the device ID for the use case (signed, for error) */
4461 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4462 if (device_id < 0)
4463 continue;
4464
4465 /* prepare structures for device probing */
4466 memset(&uc_info, 0, sizeof(uc_info));
4467 uc_info.id = audio_usecase;
4468 uc_info.type = usecase_type;
4469 if (dir) {
4470 adev->active_input = &in;
4471 memset(&in, 0, sizeof(in));
4472 in.device = audio_device;
4473 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4474 uc_info.stream.in = &in;
4475 } else {
4476 adev->active_input = NULL;
4477 }
4478 memset(&out, 0, sizeof(out));
4479 out.devices = audio_device; /* only field needed in select_devices */
4480 uc_info.stream.out = &out;
4481 uc_info.devices = audio_device;
4482 uc_info.in_snd_device = SND_DEVICE_NONE;
4483 uc_info.out_snd_device = SND_DEVICE_NONE;
4484 list_add_tail(&adev->usecase_list, &uc_info.list);
4485
4486 /* select device - similar to start_(in/out)put_stream() */
4487 retval = select_devices(adev, audio_usecase);
4488 if (retval >= 0) {
4489 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4490#if LOG_NDEBUG == 0
4491 if (*pparams) {
4492 ALOGV("%s: (%s) card %d device %d", __func__,
4493 dir ? "input" : "output", card_id, device_id);
4494 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004495 } else {
4496 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4497 }
4498#endif
4499 }
4500
4501 /* deselect device - similar to stop_(in/out)put_stream() */
4502 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004503 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004504 /* 2. Disable the rx device */
4505 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004506 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004507 list_remove(&uc_info.list);
4508 }
4509 }
4510 adev->active_input = NULL; /* restore adev state */
4511 return 0;
4512}
4513
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004514static int adev_close(hw_device_t *device)
4515{
Andy Hung31aca912014-03-20 17:14:59 -07004516 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004518
4519 if (!adev)
4520 return 0;
4521
Kevin Rocarda5453442017-05-02 15:09:20 -07004522 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004523 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004524
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004525 audio_extn_tfa_98xx_deinit();
4526
vivek mehta1a9b7c02015-06-25 11:49:38 -07004527 pthread_mutex_lock(&adev_init_lock);
4528
4529 if ((--audio_device_ref_count) == 0) {
4530 audio_route_free(adev->audio_route);
4531 free(adev->snd_dev_ref_cnt);
4532 platform_deinit(adev->platform);
4533 audio_extn_extspk_deinit(adev->extspk);
4534 audio_extn_sound_trigger_deinit(adev);
4535 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4536 pcm_params_free(adev->use_case_table[i]);
4537 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004538 if (adev->adm_deinit)
4539 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004540 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004541 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004542
4543 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004544
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004545 return 0;
4546}
4547
Glenn Kasten4f993392014-05-14 07:30:48 -07004548/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4549 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4550 * just that it _might_ work.
4551 */
4552static int period_size_is_plausible_for_low_latency(int period_size)
4553{
4554 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004555 case 48:
4556 case 96:
4557 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004558 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004559 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004560 case 240:
4561 case 320:
4562 case 480:
4563 return 1;
4564 default:
4565 return 0;
4566 }
4567}
4568
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004569static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4570{
4571 int card;
4572 card_status_t status;
4573
4574 if (!parms)
4575 return;
4576
4577 if (parse_snd_card_status(parms, &card, &status) < 0)
4578 return;
4579
4580 pthread_mutex_lock(&adev->lock);
4581 bool valid_cb = (card == adev->snd_card);
4582 if (valid_cb) {
4583 if (adev->card_status != status) {
4584 adev->card_status = status;
4585 platform_snd_card_update(adev->platform, status);
4586 }
4587 }
4588 pthread_mutex_unlock(&adev->lock);
4589 return;
4590}
4591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592static int adev_open(const hw_module_t *module, const char *name,
4593 hw_device_t **device)
4594{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004595 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596
Eric Laurent2bafff12016-03-17 12:17:23 -07004597 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004599 pthread_mutex_lock(&adev_init_lock);
4600 if (audio_device_ref_count != 0) {
4601 *device = &adev->device.common;
4602 audio_device_ref_count++;
4603 ALOGV("%s: returning existing instance of adev", __func__);
4604 ALOGV("%s: exit", __func__);
4605 pthread_mutex_unlock(&adev_init_lock);
4606 return 0;
4607 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004608 adev = calloc(1, sizeof(struct audio_device));
4609
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004610 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004612 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4613 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4614 adev->device.common.module = (struct hw_module_t *)module;
4615 adev->device.common.close = adev_close;
4616
4617 adev->device.init_check = adev_init_check;
4618 adev->device.set_voice_volume = adev_set_voice_volume;
4619 adev->device.set_master_volume = adev_set_master_volume;
4620 adev->device.get_master_volume = adev_get_master_volume;
4621 adev->device.set_master_mute = adev_set_master_mute;
4622 adev->device.get_master_mute = adev_get_master_mute;
4623 adev->device.set_mode = adev_set_mode;
4624 adev->device.set_mic_mute = adev_set_mic_mute;
4625 adev->device.get_mic_mute = adev_get_mic_mute;
4626 adev->device.set_parameters = adev_set_parameters;
4627 adev->device.get_parameters = adev_get_parameters;
4628 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4629 adev->device.open_output_stream = adev_open_output_stream;
4630 adev->device.close_output_stream = adev_close_output_stream;
4631 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004633 adev->device.close_input_stream = adev_close_input_stream;
4634 adev->device.dump = adev_dump;
4635
4636 /* Set the default route before the PCM stream is opened */
4637 pthread_mutex_lock(&adev->lock);
4638 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004639 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004640 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004642 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004643 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004644 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004645 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004646 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647 pthread_mutex_unlock(&adev->lock);
4648
4649 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004650 adev->platform = platform_init(adev);
4651 if (!adev->platform) {
4652 free(adev->snd_dev_ref_cnt);
4653 free(adev);
4654 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4655 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004656 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004657 return -EINVAL;
4658 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004659 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004660 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004661
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004662 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4663 if (adev->visualizer_lib == NULL) {
4664 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4665 } else {
4666 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4667 adev->visualizer_start_output =
4668 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4669 "visualizer_hal_start_output");
4670 adev->visualizer_stop_output =
4671 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4672 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004673 }
4674
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004675 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4676 if (adev->offload_effects_lib == NULL) {
4677 ALOGW("%s: DLOPEN failed for %s", __func__,
4678 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4679 } else {
4680 ALOGV("%s: DLOPEN successful for %s", __func__,
4681 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4682 adev->offload_effects_start_output =
4683 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4684 "offload_effects_bundle_hal_start_output");
4685 adev->offload_effects_stop_output =
4686 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4687 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004688 }
4689
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004690 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4691 if (adev->adm_lib == NULL) {
4692 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4693 } else {
4694 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4695 adev->adm_init = (adm_init_t)
4696 dlsym(adev->adm_lib, "adm_init");
4697 adev->adm_deinit = (adm_deinit_t)
4698 dlsym(adev->adm_lib, "adm_deinit");
4699 adev->adm_register_input_stream = (adm_register_input_stream_t)
4700 dlsym(adev->adm_lib, "adm_register_input_stream");
4701 adev->adm_register_output_stream = (adm_register_output_stream_t)
4702 dlsym(adev->adm_lib, "adm_register_output_stream");
4703 adev->adm_deregister_stream = (adm_deregister_stream_t)
4704 dlsym(adev->adm_lib, "adm_deregister_stream");
4705 adev->adm_request_focus = (adm_request_focus_t)
4706 dlsym(adev->adm_lib, "adm_request_focus");
4707 adev->adm_abandon_focus = (adm_abandon_focus_t)
4708 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004709 adev->adm_set_config = (adm_set_config_t)
4710 dlsym(adev->adm_lib, "adm_set_config");
4711 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4712 dlsym(adev->adm_lib, "adm_request_focus_v2");
4713 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4714 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4715 adev->adm_on_routing_change = (adm_on_routing_change_t)
4716 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004717 }
4718
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004719 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004720 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004722 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004723
Andy Hung31aca912014-03-20 17:14:59 -07004724 if (k_enable_extended_precision)
4725 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004726
Glenn Kasten4f993392014-05-14 07:30:48 -07004727 char value[PROPERTY_VALUE_MAX];
4728 int trial;
4729 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4730 trial = atoi(value);
4731 if (period_size_is_plausible_for_low_latency(trial)) {
4732 pcm_config_low_latency.period_size = trial;
4733 pcm_config_low_latency.start_threshold = trial / 4;
4734 pcm_config_low_latency.avail_min = trial / 4;
4735 configured_low_latency_capture_period_size = trial;
4736 }
4737 }
4738 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4739 trial = atoi(value);
4740 if (period_size_is_plausible_for_low_latency(trial)) {
4741 configured_low_latency_capture_period_size = trial;
4742 }
4743 }
4744
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004745 // commented as full set of app type cfg is sent from platform
4746 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004747 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004748
4749 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4750 af_period_multiplier = atoi(value);
4751 if (af_period_multiplier < 0) {
4752 af_period_multiplier = 2;
4753 } else if (af_period_multiplier > 4) {
4754 af_period_multiplier = 4;
4755 }
4756 ALOGV("new period_multiplier = %d", af_period_multiplier);
4757 }
4758
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004759 audio_extn_tfa_98xx_init(adev);
4760
vivek mehta1a9b7c02015-06-25 11:49:38 -07004761 pthread_mutex_unlock(&adev_init_lock);
4762
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004763 if (adev->adm_init)
4764 adev->adm_data = adev->adm_init();
4765
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004766 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004767 audio_extn_snd_mon_init();
4768 pthread_mutex_lock(&adev->lock);
4769 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4770 adev->card_status = CARD_STATUS_ONLINE;
4771 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004772
Eric Laurent2bafff12016-03-17 12:17:23 -07004773 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004774 return 0;
4775}
4776
4777static struct hw_module_methods_t hal_module_methods = {
4778 .open = adev_open,
4779};
4780
4781struct audio_module HAL_MODULE_INFO_SYM = {
4782 .common = {
4783 .tag = HARDWARE_MODULE_TAG,
4784 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4785 .hal_api_version = HARDWARE_HAL_API_VERSION,
4786 .id = AUDIO_HARDWARE_MODULE_ID,
4787 .name = "QCOM Audio HAL",
4788 .author = "Code Aurora Forum",
4789 .methods = &hal_module_methods,
4790 },
4791};