blob: 115181a64d9df505a11c28da081ef3541c468039 [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
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080038#include <log/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070076#define PROXY_OPEN_RETRY_COUNT 100
77#define PROXY_OPEN_WAIT_TIME 20
78
vivek mehtadae44712015-07-27 14:13:18 -070079#define MIN_CHANNEL_COUNT 1
80#define DEFAULT_CHANNEL_COUNT 2
81
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
83#define MAX_CHANNEL_COUNT 1
84#else
vivek mehtadae44712015-07-27 14:13:18 -070085#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
86#define XSTR(x) STR(x)
87#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#endif
Eric Laurent74b55762017-07-09 17:04:53 -070089#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070090
Haynes Mathew George03c40102016-01-29 17:57:48 -080091#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
92
Glenn Kasten4f993392014-05-14 07:30:48 -070093static unsigned int configured_low_latency_capture_period_size =
94 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
95
Eric Laurent0e46adf2016-12-16 12:49:24 -080096
97#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080098#define MMAP_PERIOD_COUNT_MIN 32
99#define MMAP_PERIOD_COUNT_MAX 512
100#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
Andy Hung31aca912014-03-20 17:14:59 -0700102/* This constant enables extended precision handling.
103 * TODO The flag is off until more testing is done.
104 */
105static const bool k_enable_extended_precision = false;
106
Eric Laurentb23d5282013-05-14 15:27:20 -0700107struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700108 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700109 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
110 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
111 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
112 .format = PCM_FORMAT_S16_LE,
113 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
114 .stop_threshold = INT_MAX,
115 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
116};
117
118struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700119 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700120 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
121 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
122 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
123 .format = PCM_FORMAT_S16_LE,
124 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
125 .stop_threshold = INT_MAX,
126 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
127};
128
Haynes Mathew George03c40102016-01-29 17:57:48 -0800129static int af_period_multiplier = 4;
130struct pcm_config pcm_config_rt = {
131 .channels = DEFAULT_CHANNEL_COUNT,
132 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
133 .period_size = ULL_PERIOD_SIZE, //1 ms
134 .period_count = 512, //=> buffer size is 512ms
135 .format = PCM_FORMAT_S16_LE,
136 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
137 .stop_threshold = INT_MAX,
138 .silence_threshold = 0,
139 .silence_size = 0,
140 .avail_min = ULL_PERIOD_SIZE, //1 ms
141};
142
Eric Laurentb23d5282013-05-14 15:27:20 -0700143struct pcm_config pcm_config_hdmi_multi = {
144 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
145 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
146 .period_size = HDMI_MULTI_PERIOD_SIZE,
147 .period_count = HDMI_MULTI_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = 0,
150 .stop_threshold = INT_MAX,
151 .avail_min = 0,
152};
153
Eric Laurent0e46adf2016-12-16 12:49:24 -0800154struct pcm_config pcm_config_mmap_playback = {
155 .channels = DEFAULT_CHANNEL_COUNT,
156 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
157 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800158 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = MMAP_PERIOD_SIZE*8,
161 .stop_threshold = INT32_MAX,
162 .silence_threshold = 0,
163 .silence_size = 0,
164 .avail_min = MMAP_PERIOD_SIZE, //1 ms
165};
166
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800167struct pcm_config pcm_config_hifi = {
168 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
169 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
170 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
171 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
172 .format = PCM_FORMAT_S24_3LE,
173 .start_threshold = 0,
174 .stop_threshold = INT_MAX,
175 .avail_min = 0,
176};
177
Eric Laurentb23d5282013-05-14 15:27:20 -0700178struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700179 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
181 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700182 .stop_threshold = INT_MAX,
183 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700184};
185
Haynes Mathew George03c40102016-01-29 17:57:48 -0800186struct pcm_config pcm_config_audio_capture_rt = {
187 .channels = DEFAULT_CHANNEL_COUNT,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = ULL_PERIOD_SIZE,
190 .period_count = 512,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = 0,
193 .stop_threshold = INT_MAX,
194 .silence_threshold = 0,
195 .silence_size = 0,
196 .avail_min = ULL_PERIOD_SIZE, //1 ms
197};
198
Eric Laurent0e46adf2016-12-16 12:49:24 -0800199struct pcm_config pcm_config_mmap_capture = {
200 .channels = DEFAULT_CHANNEL_COUNT,
201 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
202 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800203 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800204 .format = PCM_FORMAT_S16_LE,
205 .start_threshold = 0,
206 .stop_threshold = INT_MAX,
207 .silence_threshold = 0,
208 .silence_size = 0,
209 .avail_min = MMAP_PERIOD_SIZE, //1 ms
210};
211
vivek mehtaa68fea62017-06-08 19:04:02 -0700212struct pcm_config pcm_config_voip = {
213 .channels = 1,
214 .period_count = 2,
215 .format = PCM_FORMAT_S16_LE,
216 .stop_threshold = INT_MAX,
217 .avail_min = 0,
218};
219
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700220#define AFE_PROXY_CHANNEL_COUNT 2
221#define AFE_PROXY_SAMPLING_RATE 48000
222
223#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
224#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
225
226struct pcm_config pcm_config_afe_proxy_playback = {
227 .channels = AFE_PROXY_CHANNEL_COUNT,
228 .rate = AFE_PROXY_SAMPLING_RATE,
229 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
230 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
233 .stop_threshold = INT_MAX,
234 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235};
236
237#define AFE_PROXY_RECORD_PERIOD_SIZE 768
238#define AFE_PROXY_RECORD_PERIOD_COUNT 4
239
240struct pcm_config pcm_config_afe_proxy_record = {
241 .channels = AFE_PROXY_CHANNEL_COUNT,
242 .rate = AFE_PROXY_SAMPLING_RATE,
243 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
244 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
245 .format = PCM_FORMAT_S16_LE,
246 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
247 .stop_threshold = INT_MAX,
248 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
249};
250
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700251const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700252 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
253 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800254 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700255 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700256 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700257 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800258 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700259
Eric Laurentb23d5282013-05-14 15:27:20 -0700260 [USECASE_AUDIO_RECORD] = "audio-record",
261 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800262 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700263 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800265 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
266 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700267
Eric Laurentb23d5282013-05-14 15:27:20 -0700268 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269 [USECASE_VOICE2_CALL] = "voice2-call",
270 [USECASE_VOLTE_CALL] = "volte-call",
271 [USECASE_QCHAT_CALL] = "qchat-call",
272 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800273 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
274 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700275
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700276 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
277 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
278
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700279 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
280 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700281
282 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
283 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
284 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
285
vivek mehtaa68fea62017-06-08 19:04:02 -0700286 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
287 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200288
289 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Eric Laurentb23d5282013-05-14 15:27:20 -0700290};
291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800292
293#define STRING_TO_ENUM(string) { #string, string }
294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800295struct string_to_enum {
296 const char *name;
297 uint32_t value;
298};
299
Haynes Mathew George569b7482017-05-08 14:44:27 -0700300static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800301 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
302 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
303 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700304 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700305 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700306 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
307 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
308 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
309 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
310 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
311 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
312 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800315};
316
Haynes Mathew George5191a852013-09-11 14:19:36 -0700317static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700318static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700319static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700320static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700321//cache last MBDRC cal step level
322static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700323
Haynes Mathew George03c40102016-01-29 17:57:48 -0800324static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
325 int flags __unused)
326{
327 int dir = 0;
328 switch (uc_id) {
329 case USECASE_AUDIO_RECORD_LOW_LATENCY:
330 dir = 1;
331 case USECASE_AUDIO_PLAYBACK_ULL:
332 break;
333 default:
334 return false;
335 }
336
337 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
338 PCM_PLAYBACK : PCM_CAPTURE);
339 if (adev->adm_is_noirq_avail)
340 return adev->adm_is_noirq_avail(adev->adm_data,
341 adev->snd_card, dev_id, dir);
342 return false;
343}
344
345static void register_out_stream(struct stream_out *out)
346{
347 struct audio_device *adev = out->dev;
348 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
349 return;
350
351 if (!adev->adm_register_output_stream)
352 return;
353
354 adev->adm_register_output_stream(adev->adm_data,
355 out->handle,
356 out->flags);
357
358 if (!adev->adm_set_config)
359 return;
360
361 if (out->realtime) {
362 adev->adm_set_config(adev->adm_data,
363 out->handle,
364 out->pcm, &out->config);
365 }
366}
367
368static void register_in_stream(struct stream_in *in)
369{
370 struct audio_device *adev = in->dev;
371 if (!adev->adm_register_input_stream)
372 return;
373
374 adev->adm_register_input_stream(adev->adm_data,
375 in->capture_handle,
376 in->flags);
377
378 if (!adev->adm_set_config)
379 return;
380
381 if (in->realtime) {
382 adev->adm_set_config(adev->adm_data,
383 in->capture_handle,
384 in->pcm,
385 &in->config);
386 }
387}
388
389static void request_out_focus(struct stream_out *out, long ns)
390{
391 struct audio_device *adev = out->dev;
392
Haynes Mathew George03c40102016-01-29 17:57:48 -0800393 if (adev->adm_request_focus_v2) {
394 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
395 } else if (adev->adm_request_focus) {
396 adev->adm_request_focus(adev->adm_data, out->handle);
397 }
398}
399
400static void request_in_focus(struct stream_in *in, long ns)
401{
402 struct audio_device *adev = in->dev;
403
Haynes Mathew George03c40102016-01-29 17:57:48 -0800404 if (adev->adm_request_focus_v2) {
405 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
406 } else if (adev->adm_request_focus) {
407 adev->adm_request_focus(adev->adm_data, in->capture_handle);
408 }
409}
410
411static void release_out_focus(struct stream_out *out, long ns __unused)
412{
413 struct audio_device *adev = out->dev;
414
415 if (adev->adm_abandon_focus)
416 adev->adm_abandon_focus(adev->adm_data, out->handle);
417}
418
419static void release_in_focus(struct stream_in *in, long ns __unused)
420{
421 struct audio_device *adev = in->dev;
422 if (adev->adm_abandon_focus)
423 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
424}
425
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700426static int parse_snd_card_status(struct str_parms * parms, int * card,
427 card_status_t * status)
428{
429 char value[32]={0};
430 char state[32]={0};
431
432 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
433
434 if (ret < 0)
435 return -1;
436
437 // sscanf should be okay as value is of max length 32.
438 // same as sizeof state.
439 if (sscanf(value, "%d,%s", card, state) < 2)
440 return -1;
441
442 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
443 CARD_STATUS_OFFLINE;
444 return 0;
445}
446
vivek mehta40125092017-08-21 18:48:51 -0700447// always call with adev lock held
448void send_gain_dep_calibration_l() {
449 if (last_known_cal_step >= 0)
450 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
451}
452
vivek mehta1a9b7c02015-06-25 11:49:38 -0700453__attribute__ ((visibility ("default")))
454bool audio_hw_send_gain_dep_calibration(int level) {
455 bool ret_val = false;
456 ALOGV("%s: enter ... ", __func__);
457
458 pthread_mutex_lock(&adev_init_lock);
459
460 if (adev != NULL && adev->platform != NULL) {
461 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700462 last_known_cal_step = level;
463 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700464 pthread_mutex_unlock(&adev->lock);
465 } else {
466 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
467 }
468
469 pthread_mutex_unlock(&adev_init_lock);
470
471 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
472 return ret_val;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
vivek mehtaa8d7c922016-05-25 14:40:44 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent8251ac82014-07-23 11:00:25 -0700498 switch (format) {
499 case AUDIO_FORMAT_MP3:
500 case AUDIO_FORMAT_AAC_LC:
501 case AUDIO_FORMAT_AAC_HE_V1:
502 case AUDIO_FORMAT_AAC_HE_V2:
503 return true;
504 default:
505 break;
506 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700507 return false;
508}
509
Haynes Mathew George03c40102016-01-29 17:57:48 -0800510static inline bool is_mmap_usecase(audio_usecase_t uc_id)
511{
512 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
513 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
514}
515
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700516static int get_snd_codec_id(audio_format_t format)
517{
518 int id = 0;
519
Eric Laurent8251ac82014-07-23 11:00:25 -0700520 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521 case AUDIO_FORMAT_MP3:
522 id = SND_AUDIOCODEC_MP3;
523 break;
524 case AUDIO_FORMAT_AAC:
525 id = SND_AUDIOCODEC_AAC;
526 break;
527 default:
528 ALOGE("%s: Unsupported audio format", __func__);
529 }
530
531 return id;
532}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800533
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800534static int audio_ssr_status(struct audio_device *adev)
535{
536 int ret = 0;
537 struct mixer_ctl *ctl;
538 const char *mixer_ctl_name = "Audio SSR Status";
539
540 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
541 ret = mixer_ctl_get_value(ctl, 0);
542 ALOGD("%s: value: %d", __func__, ret);
543 return ret;
544}
545
vivek mehta4a824772017-06-08 19:05:49 -0700546static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
547{
548 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
549}
550
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800551int enable_audio_route(struct audio_device *adev,
552 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800553{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700554 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800556
557 if (usecase == NULL)
558 return -EINVAL;
559
560 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
561
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800562 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800564 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530566 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800567 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800568 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500569 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000570 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700571 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700572 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 ALOGV("%s: exit", __func__);
575 return 0;
576}
577
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800578int disable_audio_route(struct audio_device *adev,
579 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800580{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700581 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800583
584 if (usecase == NULL)
585 return -EINVAL;
586
587 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588 if (usecase->type == PCM_CAPTURE)
589 snd_device = usecase->in_snd_device;
590 else
591 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800592 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500593 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700594 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700595 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000596 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800598 ALOGV("%s: exit", __func__);
599 return 0;
600}
601
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800602int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700603 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700605 int i, num_devices = 0;
606 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800607 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800608 if (snd_device < SND_DEVICE_MIN ||
609 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800610 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800611 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800612 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700614 platform_send_audio_calibration(adev->platform, snd_device);
615
vivek mehtade4849c2016-03-03 17:23:38 -0800616 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700617 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700618 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800619 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 }
621
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700622 /* due to the possibility of calibration overwrite between listen
623 and audio, notify sound trigger hal before audio calibration is sent */
624 audio_extn_sound_trigger_update_device_status(snd_device,
625 ST_EVENT_SND_DEVICE_BUSY);
626
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700627 if (audio_extn_spkr_prot_is_enabled())
628 audio_extn_spkr_prot_calib_cancel(adev);
629
zhaoyang yin4211fad2015-06-04 21:13:25 +0800630 audio_extn_dsm_feedback_enable(adev, snd_device, true);
631
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700632 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800633 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700634 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
635 audio_extn_spkr_prot_is_enabled()) {
636 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800637 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700638 }
639 if (audio_extn_spkr_prot_start_processing(snd_device)) {
640 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800641 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700642 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700643 } else if (platform_can_split_snd_device(snd_device,
644 &num_devices,
645 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700646 for (i = 0; i < num_devices; i++) {
647 enable_snd_device(adev, new_snd_devices[i]);
648 }
vivek mehtab6506412015-08-07 16:55:17 -0700649 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700650 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800651 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
652 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
653 ALOGE(" %s: Invalid sound device returned", __func__);
654 goto on_error;
655 }
Ed Tam70b5c142016-03-21 19:14:29 -0700656
Eric Laurent2e140aa2016-06-30 17:14:46 -0700657 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800658 audio_route_apply_and_update_path(adev->audio_route, device_name);
659 }
660on_success:
661 adev->snd_dev_ref_cnt[snd_device]++;
662 ret_val = 0;
663on_error:
664 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800665}
666
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800667int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700668 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800669{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700670 int i, num_devices = 0;
671 snd_device_t new_snd_devices[2];
672
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800673 if (snd_device < SND_DEVICE_MIN ||
674 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800675 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800676 return -EINVAL;
677 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700678 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
679 ALOGE("%s: device ref cnt is already 0", __func__);
680 return -EINVAL;
681 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800682 audio_extn_tfa_98xx_disable_speaker(snd_device);
683
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 adev->snd_dev_ref_cnt[snd_device]--;
685 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800686 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700687 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800688 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700689 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700690 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
691 audio_extn_spkr_prot_is_enabled()) {
692 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700693
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700694 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
695 // and does not use speaker swap. As this code causes a problem with device enable ref
696 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700697 // when speaker device is disabled, reset swap.
698 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700699 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700700
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700701 } else if (platform_can_split_snd_device(snd_device,
702 &num_devices,
703 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700704 for (i = 0; i < num_devices; i++) {
705 disable_snd_device(adev, new_snd_devices[i]);
706 }
vivek mehtab6506412015-08-07 16:55:17 -0700707 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700708 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800709 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
710 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
711 ALOGE(" %s: Invalid sound device returned", __func__);
712 return -EINVAL;
713 }
714
Eric Laurent2e140aa2016-06-30 17:14:46 -0700715 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800716 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700717 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700718 audio_extn_sound_trigger_update_device_status(snd_device,
719 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700720 }
vivek mehtab6506412015-08-07 16:55:17 -0700721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722 return 0;
723}
724
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700725/*
726 legend:
727 uc - existing usecase
728 new_uc - new usecase
729 d1, d11, d2 - SND_DEVICE enums
730 a1, a2 - corresponding ANDROID device enums
731 B, B1, B2 - backend strings
732
733case 1
734 uc->dev d1 (a1) B1
735 new_uc->dev d1 (a1), d2 (a2) B1, B2
736
737 resolution: disable and enable uc->dev on d1
738
739case 2
740 uc->dev d1 (a1) B1
741 new_uc->dev d11 (a1) B1
742
743 resolution: need to switch uc since d1 and d11 are related
744 (e.g. speaker and voice-speaker)
745 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
746
747case 3
748 uc->dev d1 (a1) B1
749 new_uc->dev d2 (a2) B2
750
751 resolution: no need to switch uc
752
753case 4
754 uc->dev d1 (a1) B
755 new_uc->dev d2 (a2) B
756
757 resolution: disable enable uc-dev on d2 since backends match
758 we cannot enable two streams on two different devices if they
759 share the same backend. e.g. if offload is on speaker device using
760 QUAD_MI2S backend and a low-latency stream is started on voice-handset
761 using the same backend, offload must also be switched to voice-handset.
762
763case 5
764 uc->dev d1 (a1) B
765 new_uc->dev d1 (a1), d2 (a2) B
766
767 resolution: disable enable uc-dev on d2 since backends match
768 we cannot enable two streams on two different devices if they
769 share the same backend.
770
771case 6
772 uc->dev d1 a1 B1
773 new_uc->dev d2 a1 B2
774
775 resolution: no need to switch
776
777case 7
778
779 uc->dev d1 (a1), d2 (a2) B1, B2
780 new_uc->dev d1 B1
781
782 resolution: no need to switch
783
784*/
785static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
786 struct audio_usecase *new_uc,
787 snd_device_t new_snd_device)
788{
789 audio_devices_t a1 = uc->stream.out->devices;
790 audio_devices_t a2 = new_uc->stream.out->devices;
791
792 snd_device_t d1 = uc->out_snd_device;
793 snd_device_t d2 = new_snd_device;
794
795 // Treat as a special case when a1 and a2 are not disjoint
796 if ((a1 != a2) && (a1 & a2)) {
797 snd_device_t d3[2];
798 int num_devices = 0;
799 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
800 &num_devices,
801 d3);
802 if (ret < 0) {
803 if (ret != -ENOSYS) {
804 ALOGW("%s failed to split snd_device %d",
805 __func__,
806 popcount(a1) > 1 ? d1 : d2);
807 }
808 goto end;
809 }
810
811 // NB: case 7 is hypothetical and isn't a practical usecase yet.
812 // But if it does happen, we need to give priority to d2 if
813 // the combo devices active on the existing usecase share a backend.
814 // This is because we cannot have a usecase active on a combo device
815 // and a new usecase requests one device in this combo pair.
816 if (platform_check_backends_match(d3[0], d3[1])) {
817 return d2; // case 5
818 } else {
819 return d1; // case 1
820 }
821 } else {
822 if (platform_check_backends_match(d1, d2)) {
823 return d2; // case 2, 4
824 } else {
825 return d1; // case 6, 3
826 }
827 }
828
829end:
830 return d2; // return whatever was calculated before.
831}
832
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700833static void check_and_route_playback_usecases(struct audio_device *adev,
834 struct audio_usecase *uc_info,
835 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836{
837 struct listnode *node;
838 struct audio_usecase *usecase;
839 bool switch_device[AUDIO_USECASE_MAX];
840 int i, num_uc_to_switch = 0;
841
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700842 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
843 uc_info,
844 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700845
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 /*
847 * This function is to make sure that all the usecases that are active on
848 * the hardware codec backend are always routed to any one device that is
849 * handled by the hardware codec.
850 * For example, if low-latency and deep-buffer usecases are currently active
851 * on speaker and out_set_parameters(headset) is received on low-latency
852 * output, then we have to make sure deep-buffer is also switched to headset,
853 * because of the limitation that both the devices cannot be enabled
854 * at the same time as they share the same backend.
855 */
856 /* Disable all the usecases on the shared backend other than the
857 specified usecase */
858 for (i = 0; i < AUDIO_USECASE_MAX; i++)
859 switch_device[i] = false;
860
861 list_for_each(node, &adev->usecase_list) {
862 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700863 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
864 continue;
865
866 if (force_routing ||
867 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700868 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
869 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700870 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
872 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700873 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700874 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 switch_device[usecase->id] = true;
876 num_uc_to_switch++;
877 }
878 }
879
880 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 list_for_each(node, &adev->usecase_list) {
882 usecase = node_to_item(node, struct audio_usecase, list);
883 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700884 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900885 }
886 }
887
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700888 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900889 list_for_each(node, &adev->usecase_list) {
890 usecase = node_to_item(node, struct audio_usecase, list);
891 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700892 d_device = derive_playback_snd_device(usecase, uc_info,
893 snd_device);
894 enable_snd_device(adev, d_device);
895 /* Update the out_snd_device before enabling the audio route */
896 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897 }
898 }
899
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 /* Re-route all the usecases on the shared backend other than the
901 specified usecase to new snd devices */
902 list_for_each(node, &adev->usecase_list) {
903 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700904 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700905 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906 }
907 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700908 }
909}
910
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700911static void check_and_route_capture_usecases(struct audio_device *adev,
912 struct audio_usecase *uc_info,
913 snd_device_t snd_device)
914{
915 struct listnode *node;
916 struct audio_usecase *usecase;
917 bool switch_device[AUDIO_USECASE_MAX];
918 int i, num_uc_to_switch = 0;
919
vivek mehta4ed66e62016-04-15 23:33:34 -0700920 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
921
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700922 /*
923 * This function is to make sure that all the active capture usecases
924 * are always routed to the same input sound device.
925 * For example, if audio-record and voice-call usecases are currently
926 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
927 * is received for voice call then we have to make sure that audio-record
928 * usecase is also switched to earpiece i.e. voice-dmic-ef,
929 * because of the limitation that two devices cannot be enabled
930 * at the same time if they share the same backend.
931 */
932 for (i = 0; i < AUDIO_USECASE_MAX; i++)
933 switch_device[i] = false;
934
935 list_for_each(node, &adev->usecase_list) {
936 usecase = node_to_item(node, struct audio_usecase, list);
937 if (usecase->type != PCM_PLAYBACK &&
938 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700939 usecase->in_snd_device != snd_device &&
940 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700941 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
942 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700943 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700944 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700945 switch_device[usecase->id] = true;
946 num_uc_to_switch++;
947 }
948 }
949
950 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
953 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700954 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700955 }
956 }
957
958 list_for_each(node, &adev->usecase_list) {
959 usecase = node_to_item(node, struct audio_usecase, list);
960 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700961 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700962 }
963 }
964
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700965 /* Re-route all the usecases on the shared backend other than the
966 specified usecase to new snd devices */
967 list_for_each(node, &adev->usecase_list) {
968 usecase = node_to_item(node, struct audio_usecase, list);
969 /* Update the in_snd_device only before enabling the audio route */
970 if (switch_device[usecase->id] ) {
971 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700972 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700973 }
974 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700975 }
976}
977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800978/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700979static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700981 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700982 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983
984 switch (channels) {
985 /*
986 * Do not handle stereo output in Multi-channel cases
987 * Stereo case is handled in normal playback path
988 */
989 case 6:
990 ALOGV("%s: HDMI supports 5.1", __func__);
991 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
992 break;
993 case 8:
994 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
995 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
996 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
997 break;
998 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700999 ALOGE("HDMI does not support multi channel playback");
1000 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001 break;
1002 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001003 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001004}
1005
Andy Hung18859412017-08-09 11:47:21 -07001006static ssize_t read_usb_sup_sample_rates(bool is_playback,
1007 uint32_t *supported_sample_rates,
1008 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001009{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001010 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1011 supported_sample_rates,
1012 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001013#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001014 for (ssize_t i=0; i<count; i++) {
1015 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1016 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001017 }
1018#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001019 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001020}
1021
Haynes Mathew George569b7482017-05-08 14:44:27 -07001022static int read_usb_sup_channel_masks(bool is_playback,
1023 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001024 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001025{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001026 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001027 int channel_count;
1028 uint32_t num_masks = 0;
1029 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1030 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001031 }
Eric Laurent74b55762017-07-09 17:04:53 -07001032 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001033 // start from 2 channels as framework currently doesn't support mono.
1034 // TODO: consider only supporting channel index masks beyond stereo here.
1035 for (channel_count = FCC_2;
1036 channel_count <= channels && num_masks < max_masks;
1037 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001038 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1039 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001040 for (channel_count = FCC_2;
1041 channel_count <= channels && num_masks < max_masks;
1042 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001043 supported_channel_masks[num_masks++] =
1044 audio_channel_mask_for_index_assignment_from_count(channel_count);
1045 }
1046 } else {
1047 // For capture we report all supported channel masks from 1 channel up.
1048 channel_count = MIN_CHANNEL_COUNT;
1049 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1050 // indexed mask
1051 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1052 supported_channel_masks[num_masks++] =
1053 audio_channel_in_mask_from_count(channel_count);
1054 }
1055 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001056#ifdef NDEBUG
1057 for (size_t i = 0; i < num_masks; ++i) {
1058 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1059 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1060 }
1061#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001062 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001063}
1064
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001065static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001066 audio_format_t *supported_formats,
1067 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001068{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001069 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001070 switch (bitwidth) {
1071 case 24:
1072 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001073 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001074 break;
1075 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001076 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001077 break;
1078 case 16:
1079 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001080 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001081 break;
1082 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001083 ALOGV("%s: %s supported format %d", __func__,
1084 is_playback ? "P" : "C", bitwidth);
1085 return 1;
1086}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001087
Haynes Mathew George569b7482017-05-08 14:44:27 -07001088static int read_usb_sup_params_and_compare(bool is_playback,
1089 audio_format_t *format,
1090 audio_format_t *supported_formats,
1091 uint32_t max_formats,
1092 audio_channel_mask_t *mask,
1093 audio_channel_mask_t *supported_channel_masks,
1094 uint32_t max_masks,
1095 uint32_t *rate,
1096 uint32_t *supported_sample_rates,
1097 uint32_t max_rates) {
1098 int ret = 0;
1099 int num_formats;
1100 int num_masks;
1101 int num_rates;
1102 int i;
1103
1104 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1105 max_formats);
1106 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1107 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001108
Haynes Mathew George569b7482017-05-08 14:44:27 -07001109 num_rates = read_usb_sup_sample_rates(is_playback,
1110 supported_sample_rates, max_rates);
1111
1112#define LUT(table, len, what, dflt) \
1113 for (i=0; i<len && (table[i] != what); i++); \
1114 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1115
1116 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1117 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1118 LUT(supported_sample_rates, num_rates, *rate, 0);
1119
1120#undef LUT
1121 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001122}
1123
Andy Hungd9653bd2017-08-01 19:31:39 -07001124static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1125{
1126 // Check if usb is ready.
1127 // The usb device may have been removed quickly after insertion and hence
1128 // no longer available. This will show up as empty channel masks, or rates.
1129
1130 pthread_mutex_lock(&adev->lock);
1131 uint32_t supported_sample_rate;
1132
1133 // we consider usb ready if we can fetch at least one sample rate.
1134 const bool ready = read_usb_sup_sample_rates(
1135 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1136 pthread_mutex_unlock(&adev->lock);
1137 return ready;
1138}
1139
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001140static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1141{
1142 struct audio_usecase *usecase;
1143 struct listnode *node;
1144
1145 list_for_each(node, &adev->usecase_list) {
1146 usecase = node_to_item(node, struct audio_usecase, list);
1147 if (usecase->type == VOICE_CALL) {
1148 ALOGV("%s: usecase id %d", __func__, usecase->id);
1149 return usecase->id;
1150 }
1151 }
1152 return USECASE_INVALID;
1153}
1154
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001155struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1156 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001157{
1158 struct audio_usecase *usecase;
1159 struct listnode *node;
1160
1161 list_for_each(node, &adev->usecase_list) {
1162 usecase = node_to_item(node, struct audio_usecase, list);
1163 if (usecase->id == uc_id)
1164 return usecase;
1165 }
1166 return NULL;
1167}
1168
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001169int select_devices(struct audio_device *adev,
1170 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001171{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001172 snd_device_t out_snd_device = SND_DEVICE_NONE;
1173 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001174 struct audio_usecase *usecase = NULL;
1175 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001176 struct audio_usecase *hfp_usecase = NULL;
1177 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001178 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001180 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1181 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001182
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001183 usecase = get_usecase_from_list(adev, uc_id);
1184 if (usecase == NULL) {
1185 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1186 return -EINVAL;
1187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001189 if ((usecase->type == VOICE_CALL) ||
1190 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001191 out_snd_device = platform_get_output_snd_device(adev->platform,
1192 usecase->stream.out->devices);
1193 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 usecase->devices = usecase->stream.out->devices;
1195 } else {
1196 /*
1197 * If the voice call is active, use the sound devices of voice call usecase
1198 * so that it would not result any device switch. All the usecases will
1199 * be switched to new device when select_devices() is called for voice call
1200 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001201 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001203 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001204 vc_usecase = get_usecase_from_list(adev,
1205 get_voice_usecase_id_from_list(adev));
1206 if ((vc_usecase != NULL) &&
1207 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1208 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001209 in_snd_device = vc_usecase->in_snd_device;
1210 out_snd_device = vc_usecase->out_snd_device;
1211 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001212 } else if (audio_extn_hfp_is_active(adev)) {
1213 hfp_ucid = audio_extn_hfp_get_usecase();
1214 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1215 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1216 in_snd_device = hfp_usecase->in_snd_device;
1217 out_snd_device = hfp_usecase->out_snd_device;
1218 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001219 }
1220 if (usecase->type == PCM_PLAYBACK) {
1221 usecase->devices = usecase->stream.out->devices;
1222 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001223 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001224 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001225
Eric Laurentb23d5282013-05-14 15:27:20 -07001226 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001227 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001228
1229 if (voip_usecase)
1230 voip_out = voip_usecase->stream.out;
1231
1232 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001233 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001234 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001235 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001236 select_devices(adev, adev->active_input->usecase);
1237 }
1238 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001239 } else if (usecase->type == PCM_CAPTURE) {
1240 usecase->devices = usecase->stream.in->device;
1241 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001242 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001243 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001244 if (adev->active_input &&
1245 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1246 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001247
1248 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1249 USECASE_AUDIO_PLAYBACK_VOIP);
1250
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001251 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001252 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1253 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001254 } else if (voip_usecase) {
1255 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001256 } else if (adev->primary_output) {
1257 out_device = adev->primary_output->devices;
1258 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001259 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001260 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001261 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001262 }
1263 }
1264
1265 if (out_snd_device == usecase->out_snd_device &&
1266 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267 return 0;
1268 }
1269
Eric Laurent2bafff12016-03-17 12:17:23 -07001270 if (out_snd_device != SND_DEVICE_NONE &&
1271 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1272 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1273 __func__,
1274 use_case_table[uc_id],
1275 adev->last_logged_snd_device[uc_id][0],
1276 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1277 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1278 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1279 -1,
1280 out_snd_device,
1281 platform_get_snd_device_name(out_snd_device),
1282 platform_get_snd_device_acdb_id(out_snd_device));
1283 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1284 }
1285 if (in_snd_device != SND_DEVICE_NONE &&
1286 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1287 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1288 __func__,
1289 use_case_table[uc_id],
1290 adev->last_logged_snd_device[uc_id][1],
1291 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1292 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1293 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1294 -1,
1295 in_snd_device,
1296 platform_get_snd_device_name(in_snd_device),
1297 platform_get_snd_device_acdb_id(in_snd_device));
1298 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1299 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301 /*
1302 * Limitation: While in call, to do a device switch we need to disable
1303 * and enable both RX and TX devices though one of them is same as current
1304 * device.
1305 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001306 if ((usecase->type == VOICE_CALL) &&
1307 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1308 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001309 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001310 /* Disable sidetone only if voice call already exists */
1311 if (voice_is_call_state_active(adev))
1312 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001313 }
1314
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315 /* Disable current sound devices */
1316 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001317 disable_audio_route(adev, usecase);
1318 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001319 }
1320
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001321 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001322 disable_audio_route(adev, usecase);
1323 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001324 }
1325
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001326 /* Applicable only on the targets that has external modem.
1327 * New device information should be sent to modem before enabling
1328 * the devices to reduce in-call device switch time.
1329 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001330 if ((usecase->type == VOICE_CALL) &&
1331 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1332 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001333 status = platform_switch_voice_call_enable_device_config(adev->platform,
1334 out_snd_device,
1335 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001336 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001337
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338 /* Enable new sound devices */
1339 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001340 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001341 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001342 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001343 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 }
1345
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001346 if (in_snd_device != SND_DEVICE_NONE) {
1347 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001348 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001349 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001350
Eric Laurentb23d5282013-05-14 15:27:20 -07001351 if (usecase->type == VOICE_CALL)
1352 status = platform_switch_voice_call_device_post(adev->platform,
1353 out_snd_device,
1354 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001355
sangwoo170731f2013-06-08 15:36:36 +09001356 usecase->in_snd_device = in_snd_device;
1357 usecase->out_snd_device = out_snd_device;
1358
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001359 audio_extn_tfa_98xx_set_mode();
1360
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001361 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001362
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001363 /* Applicable only on the targets that has external modem.
1364 * Enable device command should be sent to modem only after
1365 * enabling voice call mixer controls
1366 */
vivek mehta765eb642015-08-07 19:46:06 -07001367 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001368 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1369 out_snd_device,
1370 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001371 /* Enable sidetone only if voice call already exists */
1372 if (voice_is_call_state_active(adev))
1373 voice_set_sidetone(adev, out_snd_device, true);
1374 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001375
Eric Laurentf4520b02017-09-20 18:31:58 -07001376 if (usecase == voip_usecase) {
1377 struct stream_out *voip_out = voip_usecase->stream.out;
1378 audio_extn_utils_send_app_type_gain(adev,
1379 voip_out->app_type_cfg.app_type,
1380 &voip_out->app_type_cfg.gain[0]);
1381 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001382 return status;
1383}
1384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001385static int stop_input_stream(struct stream_in *in)
1386{
1387 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388 struct audio_usecase *uc_info;
1389 struct audio_device *adev = in->dev;
1390
Eric Laurent994a6932013-07-17 11:51:42 -07001391 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001392 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001393
1394 if (adev->active_input) {
1395 if (adev->active_input->usecase == in->usecase) {
1396 adev->active_input = NULL;
1397 } else {
1398 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1399 __func__,
1400 use_case_table[adev->active_input->usecase],
1401 use_case_table[in->usecase]);
1402 }
1403 }
1404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001405 uc_info = get_usecase_from_list(adev, in->usecase);
1406 if (uc_info == NULL) {
1407 ALOGE("%s: Could not find the usecase (%d) in the list",
1408 __func__, in->usecase);
1409 return -EINVAL;
1410 }
1411
vivek mehta781065c2017-04-04 12:55:01 -07001412 /* Close in-call recording streams */
1413 voice_check_and_stop_incall_rec_usecase(adev, in);
1414
Eric Laurent150dbfe2013-02-27 14:31:02 -08001415 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001416 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001417
1418 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001419 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001421 list_remove(&uc_info->list);
1422 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001423
Eric Laurent994a6932013-07-17 11:51:42 -07001424 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 return ret;
1426}
1427
1428int start_input_stream(struct stream_in *in)
1429{
1430 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001431 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432 struct audio_usecase *uc_info;
1433 struct audio_device *adev = in->dev;
1434
Eric Laurent994a6932013-07-17 11:51:42 -07001435 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001436
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001437 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1438 return -EIO;
1439
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001440 if (in->card_status == CARD_STATUS_OFFLINE ||
1441 adev->card_status == CARD_STATUS_OFFLINE) {
1442 ALOGW("in->card_status or adev->card_status offline, try again");
1443 ret = -EAGAIN;
1444 goto error_config;
1445 }
1446
vivek mehta781065c2017-04-04 12:55:01 -07001447 /* Check if source matches incall recording usecase criteria */
1448 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1449 if (ret)
1450 goto error_config;
1451 else
1452 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1453
Eric Laurentb23d5282013-05-14 15:27:20 -07001454 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455 if (in->pcm_device_id < 0) {
1456 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1457 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001458 ret = -EINVAL;
1459 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001460 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001461
1462 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1464 uc_info->id = in->usecase;
1465 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001466 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 uc_info->devices = in->device;
1468 uc_info->in_snd_device = SND_DEVICE_NONE;
1469 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001471 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001472
Wei Wangf4837d52017-11-21 14:51:20 -08001473 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001474 audio_extn_perf_lock_acquire();
1475
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477
Eric Laurent0e46adf2016-12-16 12:49:24 -08001478 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001479 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001480 ALOGE("%s: pcm stream not ready", __func__);
1481 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001482 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001483 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001484 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001485 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1486 goto error_open;
1487 }
1488 } else {
1489 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1490 unsigned int pcm_open_retry_count = 0;
1491
1492 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1493 flags |= PCM_MMAP | PCM_NOIRQ;
1494 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1495 } else if (in->realtime) {
1496 flags |= PCM_MMAP | PCM_NOIRQ;
1497 }
1498
1499 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1500 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1501
1502 while (1) {
1503 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1504 flags, &in->config);
1505 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1506 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1507 if (in->pcm != NULL) {
1508 pcm_close(in->pcm);
1509 in->pcm = NULL;
1510 }
1511 if (pcm_open_retry_count-- == 0) {
1512 ret = -EIO;
1513 goto error_open;
1514 }
1515 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1516 continue;
1517 }
1518 break;
1519 }
1520
1521 ALOGV("%s: pcm_prepare", __func__);
1522 ret = pcm_prepare(in->pcm);
1523 if (ret < 0) {
1524 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001525 pcm_close(in->pcm);
1526 in->pcm = NULL;
1527 goto error_open;
1528 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001529 if (in->realtime) {
1530 ret = pcm_start(in->pcm);
1531 if (ret < 0) {
1532 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1533 pcm_close(in->pcm);
1534 in->pcm = NULL;
1535 goto error_open;
1536 }
1537 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001538 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001539 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001540 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001541 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001542 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001543
Eric Laurent0e46adf2016-12-16 12:49:24 -08001544 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001545
1546error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001548 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001549 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001550
1551error_config:
1552 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001553 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001554 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555}
1556
Eric Laurenta1478072015-09-21 17:21:52 -07001557void lock_input_stream(struct stream_in *in)
1558{
1559 pthread_mutex_lock(&in->pre_lock);
1560 pthread_mutex_lock(&in->lock);
1561 pthread_mutex_unlock(&in->pre_lock);
1562}
1563
1564void lock_output_stream(struct stream_out *out)
1565{
1566 pthread_mutex_lock(&out->pre_lock);
1567 pthread_mutex_lock(&out->lock);
1568 pthread_mutex_unlock(&out->pre_lock);
1569}
1570
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001571/* must be called with out->lock locked */
1572static int send_offload_cmd_l(struct stream_out* out, int command)
1573{
1574 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1575
1576 ALOGVV("%s %d", __func__, command);
1577
1578 cmd->cmd = command;
1579 list_add_tail(&out->offload_cmd_list, &cmd->node);
1580 pthread_cond_signal(&out->offload_cond);
1581 return 0;
1582}
1583
1584/* must be called iwth out->lock locked */
1585static void stop_compressed_output_l(struct stream_out *out)
1586{
1587 out->offload_state = OFFLOAD_STATE_IDLE;
1588 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001589 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001590 if (out->compr != NULL) {
1591 compress_stop(out->compr);
1592 while (out->offload_thread_blocked) {
1593 pthread_cond_wait(&out->cond, &out->lock);
1594 }
1595 }
1596}
1597
1598static void *offload_thread_loop(void *context)
1599{
1600 struct stream_out *out = (struct stream_out *) context;
1601 struct listnode *item;
1602
1603 out->offload_state = OFFLOAD_STATE_IDLE;
1604 out->playback_started = 0;
1605
1606 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1607 set_sched_policy(0, SP_FOREGROUND);
1608 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1609
1610 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001611 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001612 for (;;) {
1613 struct offload_cmd *cmd = NULL;
1614 stream_callback_event_t event;
1615 bool send_callback = false;
1616
1617 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1618 __func__, list_empty(&out->offload_cmd_list),
1619 out->offload_state);
1620 if (list_empty(&out->offload_cmd_list)) {
1621 ALOGV("%s SLEEPING", __func__);
1622 pthread_cond_wait(&out->offload_cond, &out->lock);
1623 ALOGV("%s RUNNING", __func__);
1624 continue;
1625 }
1626
1627 item = list_head(&out->offload_cmd_list);
1628 cmd = node_to_item(item, struct offload_cmd, node);
1629 list_remove(item);
1630
1631 ALOGVV("%s STATE %d CMD %d out->compr %p",
1632 __func__, out->offload_state, cmd->cmd, out->compr);
1633
1634 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1635 free(cmd);
1636 break;
1637 }
1638
1639 if (out->compr == NULL) {
1640 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001641 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001642 pthread_cond_signal(&out->cond);
1643 continue;
1644 }
1645 out->offload_thread_blocked = true;
1646 pthread_mutex_unlock(&out->lock);
1647 send_callback = false;
1648 switch(cmd->cmd) {
1649 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1650 compress_wait(out->compr, -1);
1651 send_callback = true;
1652 event = STREAM_CBK_EVENT_WRITE_READY;
1653 break;
1654 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001655 compress_next_track(out->compr);
1656 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001657 send_callback = true;
1658 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001659 /* Resend the metadata for next iteration */
1660 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001661 break;
1662 case OFFLOAD_CMD_DRAIN:
1663 compress_drain(out->compr);
1664 send_callback = true;
1665 event = STREAM_CBK_EVENT_DRAIN_READY;
1666 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001667 case OFFLOAD_CMD_ERROR:
1668 send_callback = true;
1669 event = STREAM_CBK_EVENT_ERROR;
1670 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001671 default:
1672 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1673 break;
1674 }
Eric Laurenta1478072015-09-21 17:21:52 -07001675 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001676 out->offload_thread_blocked = false;
1677 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001678 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001679 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001680 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001681 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001682 free(cmd);
1683 }
1684
1685 pthread_cond_signal(&out->cond);
1686 while (!list_empty(&out->offload_cmd_list)) {
1687 item = list_head(&out->offload_cmd_list);
1688 list_remove(item);
1689 free(node_to_item(item, struct offload_cmd, node));
1690 }
1691 pthread_mutex_unlock(&out->lock);
1692
1693 return NULL;
1694}
1695
1696static int create_offload_callback_thread(struct stream_out *out)
1697{
1698 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1699 list_init(&out->offload_cmd_list);
1700 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1701 offload_thread_loop, out);
1702 return 0;
1703}
1704
1705static int destroy_offload_callback_thread(struct stream_out *out)
1706{
Eric Laurenta1478072015-09-21 17:21:52 -07001707 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001708 stop_compressed_output_l(out);
1709 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1710
1711 pthread_mutex_unlock(&out->lock);
1712 pthread_join(out->offload_thread, (void **) NULL);
1713 pthread_cond_destroy(&out->offload_cond);
1714
1715 return 0;
1716}
1717
Eric Laurent07eeafd2013-10-06 12:52:49 -07001718static bool allow_hdmi_channel_config(struct audio_device *adev)
1719{
1720 struct listnode *node;
1721 struct audio_usecase *usecase;
1722 bool ret = true;
1723
1724 list_for_each(node, &adev->usecase_list) {
1725 usecase = node_to_item(node, struct audio_usecase, list);
1726 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1727 /*
1728 * If voice call is already existing, do not proceed further to avoid
1729 * disabling/enabling both RX and TX devices, CSD calls, etc.
1730 * Once the voice call done, the HDMI channels can be configured to
1731 * max channels of remaining use cases.
1732 */
1733 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001734 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001735 __func__);
1736 ret = false;
1737 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001738 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1739 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001740 "no change in HDMI channels", __func__);
1741 ret = false;
1742 break;
1743 }
1744 }
1745 }
1746 return ret;
1747}
1748
1749static int check_and_set_hdmi_channels(struct audio_device *adev,
1750 unsigned int channels)
1751{
1752 struct listnode *node;
1753 struct audio_usecase *usecase;
1754
1755 /* Check if change in HDMI channel config is allowed */
1756 if (!allow_hdmi_channel_config(adev))
1757 return 0;
1758
1759 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001760 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001761 return 0;
1762 }
1763
1764 platform_set_hdmi_channels(adev->platform, channels);
1765 adev->cur_hdmi_channels = channels;
1766
1767 /*
1768 * Deroute all the playback streams routed to HDMI so that
1769 * the back end is deactivated. Note that backend will not
1770 * be deactivated if any one stream is connected to it.
1771 */
1772 list_for_each(node, &adev->usecase_list) {
1773 usecase = node_to_item(node, struct audio_usecase, list);
1774 if (usecase->type == PCM_PLAYBACK &&
1775 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001776 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001777 }
1778 }
1779
1780 /*
1781 * Enable all the streams disabled above. Now the HDMI backend
1782 * will be activated with new channel configuration
1783 */
1784 list_for_each(node, &adev->usecase_list) {
1785 usecase = node_to_item(node, struct audio_usecase, list);
1786 if (usecase->type == PCM_PLAYBACK &&
1787 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001788 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001789 }
1790 }
1791
1792 return 0;
1793}
1794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795static int stop_output_stream(struct stream_out *out)
1796{
1797 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 struct audio_usecase *uc_info;
1799 struct audio_device *adev = out->dev;
1800
Eric Laurent994a6932013-07-17 11:51:42 -07001801 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001802 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803 uc_info = get_usecase_from_list(adev, out->usecase);
1804 if (uc_info == NULL) {
1805 ALOGE("%s: Could not find the usecase (%d) in the list",
1806 __func__, out->usecase);
1807 return -EINVAL;
1808 }
1809
Haynes Mathew George41f86652014-06-17 14:22:15 -07001810 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1811 if (adev->visualizer_stop_output != NULL)
1812 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1813 if (adev->offload_effects_stop_output != NULL)
1814 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001815 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1816 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1817 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001818 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001819
Eric Laurent150dbfe2013-02-27 14:31:02 -08001820 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001821 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822
1823 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001824 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001826 list_remove(&uc_info->list);
1827 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828
Eric Laurent0499d4f2014-08-25 22:39:29 -05001829 audio_extn_extspk_update(adev->extspk);
1830
Eric Laurent07eeafd2013-10-06 12:52:49 -07001831 /* Must be called after removing the usecase from list */
1832 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1833 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001834 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1835 struct listnode *node;
1836 struct audio_usecase *usecase;
1837 list_for_each(node, &adev->usecase_list) {
1838 usecase = node_to_item(node, struct audio_usecase, list);
1839 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1840 select_devices(adev, usecase->id);
1841 }
1842 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001843
Eric Laurent994a6932013-07-17 11:51:42 -07001844 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 return ret;
1846}
1847
1848int start_output_stream(struct stream_out *out)
1849{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 struct audio_usecase *uc_info;
1852 struct audio_device *adev = out->dev;
1853
Eric Laurent994a6932013-07-17 11:51:42 -07001854 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001855 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001856
1857 if (out->card_status == CARD_STATUS_OFFLINE ||
1858 adev->card_status == CARD_STATUS_OFFLINE) {
1859 ALOGW("out->card_status or adev->card_status offline, try again");
1860 ret = -EAGAIN;
1861 goto error_config;
1862 }
1863
Eric Laurentb23d5282013-05-14 15:27:20 -07001864 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 if (out->pcm_device_id < 0) {
1866 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1867 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001868 ret = -EINVAL;
1869 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870 }
1871
1872 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1873 uc_info->id = out->usecase;
1874 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001875 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 uc_info->devices = out->devices;
1877 uc_info->in_snd_device = SND_DEVICE_NONE;
1878 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879
Eric Laurent07eeafd2013-10-06 12:52:49 -07001880 /* This must be called before adding this usecase to the list */
1881 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1882 check_and_set_hdmi_channels(adev, out->config.channels);
1883
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001884 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885
Wei Wangf4837d52017-11-21 14:51:20 -08001886 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001887 audio_extn_perf_lock_acquire();
1888
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 select_devices(adev, out->usecase);
1890
Eric Laurent0499d4f2014-08-25 22:39:29 -05001891 audio_extn_extspk_update(adev->extspk);
1892
Andy Hung31aca912014-03-20 17:14:59 -07001893 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001894 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001895 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1896 out->pcm = NULL;
1897 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1898 COMPRESS_IN, &out->compr_config);
1899 if (out->compr && !is_compress_ready(out->compr)) {
1900 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1901 compress_close(out->compr);
1902 out->compr = NULL;
1903 ret = -EIO;
1904 goto error_open;
1905 }
1906 if (out->offload_callback)
1907 compress_nonblock(out->compr, out->non_blocking);
1908
1909 if (adev->visualizer_start_output != NULL)
1910 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1911 if (adev->offload_effects_start_output != NULL)
1912 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1913 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001914 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001915 ALOGE("%s: pcm stream not ready", __func__);
1916 goto error_open;
1917 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001918 ret = pcm_start(out->pcm);
1919 if (ret < 0) {
1920 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1921 goto error_open;
1922 }
1923 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001924 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001925 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001926
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001927 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1928 flags |= PCM_MMAP | PCM_NOIRQ;
1929 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001930 } else if (out->realtime) {
1931 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001932 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001933
1934 while (1) {
1935 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1936 flags, &out->config);
1937 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1938 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1939 if (out->pcm != NULL) {
1940 pcm_close(out->pcm);
1941 out->pcm = NULL;
1942 }
1943 if (pcm_open_retry_count-- == 0) {
1944 ret = -EIO;
1945 goto error_open;
1946 }
1947 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1948 continue;
1949 }
1950 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001951 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001952 ALOGV("%s: pcm_prepare", __func__);
1953 if (pcm_is_ready(out->pcm)) {
1954 ret = pcm_prepare(out->pcm);
1955 if (ret < 0) {
1956 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1957 pcm_close(out->pcm);
1958 out->pcm = NULL;
1959 goto error_open;
1960 }
1961 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001962 if (out->realtime) {
1963 ret = pcm_start(out->pcm);
1964 if (ret < 0) {
1965 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1966 pcm_close(out->pcm);
1967 out->pcm = NULL;
1968 goto error_open;
1969 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001970 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001971 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001972 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08001973 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001974 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001975 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07001976
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001977 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1978 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1979 audio_low_latency_hint_start();
1980 }
1981
vivek mehtae59cfb22017-06-16 15:57:11 -07001982 // consider a scenario where on pause lower layers are tear down.
1983 // so on resume, swap mixer control need to be sent only when
1984 // backend is active, hence rather than sending from enable device
1985 // sending it from start of streamtream
1986
1987 platform_set_swap_channels(adev, true);
1988
Eric Laurent994a6932013-07-17 11:51:42 -07001989 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001990 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08001992 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001993 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001995error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001996 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997}
1998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999static int check_input_parameters(uint32_t sample_rate,
2000 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002001 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002003 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2004 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002005 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2006 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002007 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2008 return -EINVAL;
2009 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010
Eric Laurent74b55762017-07-09 17:04:53 -07002011 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2012 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002013 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002014 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002015 return -EINVAL;
2016 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017
2018 switch (sample_rate) {
2019 case 8000:
2020 case 11025:
2021 case 12000:
2022 case 16000:
2023 case 22050:
2024 case 24000:
2025 case 32000:
2026 case 44100:
2027 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002028 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 break;
2030 default:
vivek mehtadae44712015-07-27 14:13:18 -07002031 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 return -EINVAL;
2033 }
2034
2035 return 0;
2036}
2037
vivek mehtaa68fea62017-06-08 19:04:02 -07002038static size_t get_stream_buffer_size(size_t duration_ms,
2039 uint32_t sample_rate,
2040 audio_format_t format,
2041 int channel_count,
2042 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043{
2044 size_t size = 0;
2045
vivek mehtaa68fea62017-06-08 19:04:02 -07002046 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002047 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002048 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002049
2050 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051
Glenn Kasten4f993392014-05-14 07:30:48 -07002052 /* make sure the size is multiple of 32 bytes
2053 * At 48 kHz mono 16-bit PCM:
2054 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2055 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2056 */
2057 size += 0x1f;
2058 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002059
2060 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061}
2062
2063static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2064{
2065 struct stream_out *out = (struct stream_out *)stream;
2066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002067 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068}
2069
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002070static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071{
2072 return -ENOSYS;
2073}
2074
2075static size_t out_get_buffer_size(const struct audio_stream *stream)
2076{
2077 struct stream_out *out = (struct stream_out *)stream;
2078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2080 return out->compr_config.fragment_size;
2081 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002082 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002083 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084}
2085
2086static uint32_t out_get_channels(const struct audio_stream *stream)
2087{
2088 struct stream_out *out = (struct stream_out *)stream;
2089
2090 return out->channel_mask;
2091}
2092
2093static audio_format_t out_get_format(const struct audio_stream *stream)
2094{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002095 struct stream_out *out = (struct stream_out *)stream;
2096
2097 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098}
2099
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002100static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101{
2102 return -ENOSYS;
2103}
2104
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002105/* must be called with out->lock locked */
2106static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107{
2108 struct stream_out *out = (struct stream_out *)stream;
2109 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002110 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002113 if (adev->adm_deregister_stream)
2114 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002115 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2118 if (out->pcm) {
2119 pcm_close(out->pcm);
2120 out->pcm = NULL;
2121 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002122 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002123 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002124 out->playback_started = false;
2125 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002126 } else {
2127 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002128 out->gapless_mdata.encoder_delay = 0;
2129 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 if (out->compr != NULL) {
2131 compress_close(out->compr);
2132 out->compr = NULL;
2133 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002134 }
Phil Burkbc991042017-02-24 08:06:44 -08002135 if (do_stop) {
2136 stop_output_stream(out);
2137 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002138 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002140 return 0;
2141}
2142
2143static int out_standby(struct audio_stream *stream)
2144{
2145 struct stream_out *out = (struct stream_out *)stream;
2146
2147 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2148 out->usecase, use_case_table[out->usecase]);
2149
2150 lock_output_stream(out);
2151 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002153 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 return 0;
2155}
2156
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002157static int out_on_error(struct audio_stream *stream)
2158{
2159 struct stream_out *out = (struct stream_out *)stream;
2160 struct audio_device *adev = out->dev;
2161 bool do_standby = false;
2162
2163 lock_output_stream(out);
2164 if (!out->standby) {
2165 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2166 stop_compressed_output_l(out);
2167 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2168 } else
2169 do_standby = true;
2170 }
2171 pthread_mutex_unlock(&out->lock);
2172
2173 if (do_standby)
2174 return out_standby(&out->stream.common);
2175
2176 return 0;
2177}
2178
Andy Hung7401c7c2016-09-21 12:41:21 -07002179static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180{
Andy Hung7401c7c2016-09-21 12:41:21 -07002181 struct stream_out *out = (struct stream_out *)stream;
2182
2183 // We try to get the lock for consistency,
2184 // but it isn't necessary for these variables.
2185 // If we're not in standby, we may be blocked on a write.
2186 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2187 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2188 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2189
2190 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002191 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002192 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002193
2194 // dump error info
2195 (void)error_log_dump(
2196 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 return 0;
2199}
2200
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002201static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2202{
2203 int ret = 0;
2204 char value[32];
2205 struct compr_gapless_mdata tmp_mdata;
2206
2207 if (!out || !parms) {
2208 return -EINVAL;
2209 }
2210
2211 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2212 if (ret >= 0) {
2213 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2214 } else {
2215 return -EINVAL;
2216 }
2217
2218 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2219 if (ret >= 0) {
2220 tmp_mdata.encoder_padding = atoi(value);
2221 } else {
2222 return -EINVAL;
2223 }
2224
2225 out->gapless_mdata = tmp_mdata;
2226 out->send_new_metadata = 1;
2227 ALOGV("%s new encoder delay %u and padding %u", __func__,
2228 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2229
2230 return 0;
2231}
2232
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002233static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2234{
2235 return out == adev->primary_output || out == adev->voice_tx_output;
2236}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002237
Kevin Rocard1e02c882017-08-09 15:26:07 -07002238static int get_alive_usb_card(struct str_parms* parms) {
2239 int card;
2240 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2241 !audio_extn_usb_alive(card)) {
2242 return card;
2243 }
2244 return -ENODEV;
2245}
2246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2248{
2249 struct stream_out *out = (struct stream_out *)stream;
2250 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002251 struct audio_usecase *usecase;
2252 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253 struct str_parms *parms;
2254 char value[32];
2255 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002256 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002257 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258
Eric Laurent2e140aa2016-06-30 17:14:46 -07002259 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002260 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261 parms = str_parms_create_str(kvpairs);
2262 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2263 if (ret >= 0) {
2264 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002265
Eric Laurenta1478072015-09-21 17:21:52 -07002266 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002267
2268 // The usb driver needs to be closed after usb device disconnection
2269 // otherwise audio is no longer played on the new usb devices.
2270 // By forcing the stream in standby, the usb stack refcount drops to 0
2271 // and the driver is closed.
2272 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2273 audio_is_usb_out_device(out->devices)) {
2274 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2275 out_standby_l(&out->stream.common);
2276 }
2277
Eric Laurent150dbfe2013-02-27 14:31:02 -08002278 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002280 /*
2281 * When HDMI cable is unplugged the music playback is paused and
2282 * the policy manager sends routing=0. But the audioflinger
2283 * continues to write data until standby time (3sec).
2284 * As the HDMI core is turned off, the write gets blocked.
2285 * Avoid this by routing audio to speaker until standby.
2286 */
2287 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2288 val == AUDIO_DEVICE_NONE) {
2289 val = AUDIO_DEVICE_OUT_SPEAKER;
2290 }
2291
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002292 audio_devices_t new_dev = val;
2293
2294 // Workaround: If routing to an non existing usb device, fail gracefully
2295 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002296 int card;
2297 if (audio_is_usb_out_device(new_dev) &&
2298 (card = get_alive_usb_card(parms)) >= 0) {
2299
2300 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002301 pthread_mutex_unlock(&adev->lock);
2302 pthread_mutex_unlock(&out->lock);
2303 status = -ENOSYS;
2304 goto routing_fail;
2305 }
2306
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002307 /*
2308 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002309 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002310 * the select_devices(). But how do we undo this?
2311 *
2312 * For example, music playback is active on headset (deep-buffer usecase)
2313 * and if we go to ringtones and select a ringtone, low-latency usecase
2314 * will be started on headset+speaker. As we can't enable headset+speaker
2315 * and headset devices at the same time, select_devices() switches the music
2316 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2317 * So when the ringtone playback is completed, how do we undo the same?
2318 *
2319 * We are relying on the out_set_parameters() call on deep-buffer output,
2320 * once the ringtone playback is ended.
2321 * NOTE: We should not check if the current devices are same as new devices.
2322 * Because select_devices() must be called to switch back the music
2323 * playback to headset.
2324 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002325 if (new_dev != AUDIO_DEVICE_NONE) {
2326 bool same_dev = out->devices == new_dev;
2327 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002328
Eric Laurenta7657192014-10-09 21:09:33 -07002329 if (output_drives_call(adev, out)) {
2330 if (!voice_is_in_call(adev)) {
2331 if (adev->mode == AUDIO_MODE_IN_CALL) {
2332 adev->current_call_output = out;
2333 ret = voice_start_call(adev);
2334 }
2335 } else {
2336 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002337 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002338 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002339 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002340
2341 if (!out->standby) {
2342 if (!same_dev) {
2343 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002344 // inform adm before actual routing to prevent glitches.
2345 if (adev->adm_on_routing_change) {
2346 adev->adm_on_routing_change(adev->adm_data,
2347 out->handle);
2348 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002349 }
2350 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002351 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002352
2353 // on device switch force swap, lower functions will make sure
2354 // to check if swap is allowed or not.
2355
2356 if (!same_dev)
2357 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002358 }
2359
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002360 }
2361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002363 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002364
2365 /*handles device and call state changes*/
2366 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002368 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002369
2370 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2371 parse_compress_metadata(out, parms);
2372 }
2373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002375 ALOGV("%s: exit: code(%d)", __func__, status);
2376 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377}
2378
Haynes Mathew George569b7482017-05-08 14:44:27 -07002379static bool stream_get_parameter_channels(struct str_parms *query,
2380 struct str_parms *reply,
2381 audio_channel_mask_t *supported_channel_masks) {
2382 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002385 size_t i, j;
2386
2387 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2388 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 value[0] = '\0';
2390 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002391 while (supported_channel_masks[i] != 0) {
2392 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2393 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394 if (!first) {
2395 strcat(value, "|");
2396 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002397 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398 first = false;
2399 break;
2400 }
2401 }
2402 i++;
2403 }
2404 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002405 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002406 return ret >= 0;
2407}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002408
Haynes Mathew George569b7482017-05-08 14:44:27 -07002409static bool stream_get_parameter_formats(struct str_parms *query,
2410 struct str_parms *reply,
2411 audio_format_t *supported_formats) {
2412 int ret = -1;
2413 char value[256];
2414 int i;
2415
2416 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2417 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002418 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002419 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002420 case AUDIO_FORMAT_PCM_16_BIT:
2421 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2422 break;
2423 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2424 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2425 break;
2426 case AUDIO_FORMAT_PCM_32_BIT:
2427 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2428 break;
2429 default:
2430 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002431 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002432 break;
2433 }
2434 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002435 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002436 return ret >= 0;
2437}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002438
Haynes Mathew George569b7482017-05-08 14:44:27 -07002439static bool stream_get_parameter_rates(struct str_parms *query,
2440 struct str_parms *reply,
2441 uint32_t *supported_sample_rates) {
2442
2443 int i;
2444 char value[256];
2445 int ret = -1;
2446 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2447 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002448 value[0] = '\0';
2449 i=0;
2450 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002451 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002452 int avail = sizeof(value) - cursor;
2453 ret = snprintf(value + cursor, avail, "%s%d",
2454 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002455 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002456 if (ret < 0 || ret >= avail) {
2457 // if cursor is at the last element of the array
2458 // overwrite with \0 is duplicate work as
2459 // snprintf already put a \0 in place.
2460 // else
2461 // we had space to write the '|' at value[cursor]
2462 // (which will be overwritten) or no space to fill
2463 // the first element (=> cursor == 0)
2464 value[cursor] = '\0';
2465 break;
2466 }
2467 cursor += ret;
2468 ++i;
2469 }
2470 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2471 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002472 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002473 return ret >= 0;
2474}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002475
Haynes Mathew George569b7482017-05-08 14:44:27 -07002476static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2477{
2478 struct stream_out *out = (struct stream_out *)stream;
2479 struct str_parms *query = str_parms_create_str(keys);
2480 char *str;
2481 struct str_parms *reply = str_parms_create();
2482 bool replied = false;
2483 ALOGV("%s: enter: keys - %s", __func__, keys);
2484
2485 replied |= stream_get_parameter_channels(query, reply,
2486 &out->supported_channel_masks[0]);
2487 replied |= stream_get_parameter_formats(query, reply,
2488 &out->supported_formats[0]);
2489 replied |= stream_get_parameter_rates(query, reply,
2490 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002491 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 str = str_parms_to_str(reply);
2493 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002494 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495 }
2496 str_parms_destroy(query);
2497 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002498 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499 return str;
2500}
2501
2502static uint32_t out_get_latency(const struct audio_stream_out *stream)
2503{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002504 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 struct stream_out *out = (struct stream_out *)stream;
2506
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002507 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2508 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002509 else if ((out->realtime) ||
2510 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002511 // since the buffer won't be filled up faster than realtime,
2512 // return a smaller number
2513 period_ms = (out->af_period_multiplier * out->config.period_size *
2514 1000) / (out->config.rate);
2515 hw_delay = platform_render_latency(out->usecase)/1000;
2516 return period_ms + hw_delay;
2517 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002518
2519 return (out->config.period_count * out->config.period_size * 1000) /
2520 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521}
2522
2523static int out_set_volume(struct audio_stream_out *stream, float left,
2524 float right)
2525{
Eric Laurenta9024de2013-04-04 09:19:12 -07002526 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002527 int volume[2];
2528
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002529 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002530 /* only take left channel into account: the API is for stereo anyway */
2531 out->muted = (left == 0.0f);
2532 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2534 const char *mixer_ctl_name = "Compress Playback Volume";
2535 struct audio_device *adev = out->dev;
2536 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002537 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2538 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002539 /* try with the control based on device id */
2540 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2541 PCM_PLAYBACK);
2542 char ctl_name[128] = {0};
2543 snprintf(ctl_name, sizeof(ctl_name),
2544 "Compress Playback %d Volume", pcm_device_id);
2545 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2546 if (!ctl) {
2547 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2548 return -EINVAL;
2549 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002550 }
2551 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2552 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2553 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2554 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002555 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002556 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2557 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2558 if (!out->standby) {
2559 // if in standby, cached volume will be sent after stream is opened
2560 audio_extn_utils_send_app_type_gain(out->dev,
2561 out->app_type_cfg.app_type,
2562 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002563 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002564 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002565 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 return -ENOSYS;
2568}
2569
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002570// note: this call is safe only if the stream_cb is
2571// removed first in close_output_stream (as is done now).
2572static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2573{
2574 if (!stream || !parms)
2575 return;
2576
2577 struct stream_out *out = (struct stream_out *)stream;
2578 struct audio_device *adev = out->dev;
2579
2580 card_status_t status;
2581 int card;
2582 if (parse_snd_card_status(parms, &card, &status) < 0)
2583 return;
2584
2585 pthread_mutex_lock(&adev->lock);
2586 bool valid_cb = (card == adev->snd_card);
2587 pthread_mutex_unlock(&adev->lock);
2588
2589 if (!valid_cb)
2590 return;
2591
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002592 lock_output_stream(out);
2593 if (out->card_status != status)
2594 out->card_status = status;
2595 pthread_mutex_unlock(&out->lock);
2596
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002597 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2598 use_case_table[out->usecase],
2599 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2600
2601 if (status == CARD_STATUS_OFFLINE)
2602 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002603
2604 return;
2605}
2606
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002607#ifdef NO_AUDIO_OUT
2608static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002609 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002610{
2611 struct stream_out *out = (struct stream_out *)stream;
2612
2613 /* No Output device supported other than BT for playback.
2614 * Sleep for the amount of buffer duration
2615 */
Eric Laurenta1478072015-09-21 17:21:52 -07002616 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002617 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2618 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002619 out_get_sample_rate(&out->stream.common));
2620 pthread_mutex_unlock(&out->lock);
2621 return bytes;
2622}
2623#endif
2624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2626 size_t bytes)
2627{
2628 struct stream_out *out = (struct stream_out *)stream;
2629 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002630 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002631 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632
Eric Laurenta1478072015-09-21 17:21:52 -07002633 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002634 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002635 const size_t frame_size = audio_stream_out_frame_size(stream);
2636 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002637
Eric Laurent0e46adf2016-12-16 12:49:24 -08002638 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2639 error_code = ERROR_CODE_WRITE;
2640 goto exit;
2641 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002643 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002644 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002646
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002647 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002649 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002650 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 goto exit;
2652 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002653
vivek mehta40125092017-08-21 18:48:51 -07002654 // after standby always force set last known cal step
2655 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2656 ALOGD("%s: retry previous failed cal level set", __func__);
2657 send_gain_dep_calibration_l();
2658 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002661 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002662 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002663 if (out->send_new_metadata) {
2664 ALOGVV("send new gapless metadata");
2665 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2666 out->send_new_metadata = 0;
2667 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002668 unsigned int avail;
2669 struct timespec tstamp;
2670 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2671 /* Do not limit write size if the available frames count is unknown */
2672 if (ret != 0) {
2673 avail = bytes;
2674 }
2675 if (avail == 0) {
2676 ret = 0;
2677 } else {
2678 if (avail > bytes) {
2679 avail = bytes;
2680 }
2681 ret = compress_write(out->compr, buffer, avail);
2682 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2683 __func__, avail, ret);
2684 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002685
Eric Laurent6e895242013-09-05 16:10:57 -07002686 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002687 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2688 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002689 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002690 compress_start(out->compr);
2691 out->playback_started = 1;
2692 out->offload_state = OFFLOAD_STATE_PLAYING;
2693 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002694 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002695 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002696 } else {
2697 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002698 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002699 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002700 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002701 return ret;
2702 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002703 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002704 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002705 size_t bytes_to_write = bytes;
2706
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002707 if (out->muted)
2708 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002709 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02002710 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002711 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2712 int16_t *src = (int16_t *)buffer;
2713 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002714
Eric Laurentad2dde92017-09-20 18:27:31 -07002715 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2716 out->format != AUDIO_FORMAT_PCM_16_BIT,
2717 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002718
Eric Laurentad2dde92017-09-20 18:27:31 -07002719 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2720 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2721 }
2722 bytes_to_write /= 2;
2723 }
2724 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2725
Glenn Kasten5a59dff2018-02-22 08:05:35 -08002726 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002727 request_out_focus(out, ns);
2728
2729 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2730 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002731 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002732 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002733 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002734
Haynes Mathew George03c40102016-01-29 17:57:48 -08002735 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002736 } else {
2737 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 }
2740
2741exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002742 // For PCM we always consume the buffer and return #bytes regardless of ret.
2743 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002744 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002745 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002746 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002747
Andy Hung7401c7c2016-09-21 12:41:21 -07002748 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002749 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002750 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2751 ALOGE_IF(out->pcm != NULL,
2752 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002753 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002754 // usleep not guaranteed for values over 1 second but we don't limit here.
2755 }
2756 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 pthread_mutex_unlock(&out->lock);
2759
2760 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002761 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002762 if (sleeptime_us != 0)
2763 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764 }
2765 return bytes;
2766}
2767
2768static int out_get_render_position(const struct audio_stream_out *stream,
2769 uint32_t *dsp_frames)
2770{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002771 struct stream_out *out = (struct stream_out *)stream;
2772 *dsp_frames = 0;
2773 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002774 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002775 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002776 unsigned long frames = 0;
2777 // TODO: check return value
2778 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2779 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002780 ALOGVV("%s rendered frames %d sample_rate %d",
2781 __func__, *dsp_frames, out->sample_rate);
2782 }
2783 pthread_mutex_unlock(&out->lock);
2784 return 0;
2785 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002786 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787}
2788
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002789static int out_add_audio_effect(const struct audio_stream *stream __unused,
2790 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791{
2792 return 0;
2793}
2794
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002795static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2796 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797{
2798 return 0;
2799}
2800
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002801static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2802 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002804 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805}
2806
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002807static int out_get_presentation_position(const struct audio_stream_out *stream,
2808 uint64_t *frames, struct timespec *timestamp)
2809{
2810 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002811 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002812 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002813
Eric Laurenta1478072015-09-21 17:21:52 -07002814 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002815
Eric Laurent949a0892013-09-20 09:20:13 -07002816 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2817 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002818 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002819 compress_get_tstamp(out->compr, &dsp_frames,
2820 &out->sample_rate);
2821 ALOGVV("%s rendered frames %ld sample_rate %d",
2822 __func__, dsp_frames, out->sample_rate);
2823 *frames = dsp_frames;
2824 ret = 0;
2825 /* this is the best we can do */
2826 clock_gettime(CLOCK_MONOTONIC, timestamp);
2827 }
2828 } else {
2829 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002830 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002831 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2832 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002833 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002834 // This adjustment accounts for buffering after app processor.
2835 // It is based on estimated DSP latency per use case, rather than exact.
2836 signed_frames -=
2837 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2838
Eric Laurent949a0892013-09-20 09:20:13 -07002839 // It would be unusual for this value to be negative, but check just in case ...
2840 if (signed_frames >= 0) {
2841 *frames = signed_frames;
2842 ret = 0;
2843 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002844 }
2845 }
2846 }
2847
2848 pthread_mutex_unlock(&out->lock);
2849
2850 return ret;
2851}
2852
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002853static int out_set_callback(struct audio_stream_out *stream,
2854 stream_callback_t callback, void *cookie)
2855{
2856 struct stream_out *out = (struct stream_out *)stream;
2857
2858 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002859 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 out->offload_callback = callback;
2861 out->offload_cookie = cookie;
2862 pthread_mutex_unlock(&out->lock);
2863 return 0;
2864}
2865
2866static int out_pause(struct audio_stream_out* stream)
2867{
2868 struct stream_out *out = (struct stream_out *)stream;
2869 int status = -ENOSYS;
2870 ALOGV("%s", __func__);
2871 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002872 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2874 status = compress_pause(out->compr);
2875 out->offload_state = OFFLOAD_STATE_PAUSED;
2876 }
2877 pthread_mutex_unlock(&out->lock);
2878 }
2879 return status;
2880}
2881
2882static int out_resume(struct audio_stream_out* stream)
2883{
2884 struct stream_out *out = (struct stream_out *)stream;
2885 int status = -ENOSYS;
2886 ALOGV("%s", __func__);
2887 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2888 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002889 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002890 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2891 status = compress_resume(out->compr);
2892 out->offload_state = OFFLOAD_STATE_PLAYING;
2893 }
2894 pthread_mutex_unlock(&out->lock);
2895 }
2896 return status;
2897}
2898
2899static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2900{
2901 struct stream_out *out = (struct stream_out *)stream;
2902 int status = -ENOSYS;
2903 ALOGV("%s", __func__);
2904 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002905 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002906 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2907 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2908 else
2909 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2910 pthread_mutex_unlock(&out->lock);
2911 }
2912 return status;
2913}
2914
2915static int out_flush(struct audio_stream_out* stream)
2916{
2917 struct stream_out *out = (struct stream_out *)stream;
2918 ALOGV("%s", __func__);
2919 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002920 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 stop_compressed_output_l(out);
2922 pthread_mutex_unlock(&out->lock);
2923 return 0;
2924 }
2925 return -ENOSYS;
2926}
2927
Eric Laurent0e46adf2016-12-16 12:49:24 -08002928static int out_stop(const struct audio_stream_out* stream)
2929{
2930 struct stream_out *out = (struct stream_out *)stream;
2931 struct audio_device *adev = out->dev;
2932 int ret = -ENOSYS;
2933
2934 ALOGV("%s", __func__);
2935 pthread_mutex_lock(&adev->lock);
2936 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2937 out->playback_started && out->pcm != NULL) {
2938 pcm_stop(out->pcm);
2939 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002940 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002941 }
2942 pthread_mutex_unlock(&adev->lock);
2943 return ret;
2944}
2945
2946static int out_start(const struct audio_stream_out* stream)
2947{
2948 struct stream_out *out = (struct stream_out *)stream;
2949 struct audio_device *adev = out->dev;
2950 int ret = -ENOSYS;
2951
2952 ALOGV("%s", __func__);
2953 pthread_mutex_lock(&adev->lock);
2954 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2955 !out->playback_started && out->pcm != NULL) {
2956 ret = start_output_stream(out);
2957 if (ret == 0) {
2958 out->playback_started = true;
2959 }
2960 }
2961 pthread_mutex_unlock(&adev->lock);
2962 return ret;
2963}
2964
Phil Burkbc991042017-02-24 08:06:44 -08002965/*
2966 * Modify config->period_count based on min_size_frames
2967 */
2968static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2969{
2970 int periodCountRequested = (min_size_frames + config->period_size - 1)
2971 / config->period_size;
2972 int periodCount = MMAP_PERIOD_COUNT_MIN;
2973
2974 ALOGV("%s original config.period_size = %d config.period_count = %d",
2975 __func__, config->period_size, config->period_count);
2976
2977 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2978 periodCount *= 2;
2979 }
2980 config->period_count = periodCount;
2981
2982 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2983}
2984
Eric Laurent0e46adf2016-12-16 12:49:24 -08002985static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2986 int32_t min_size_frames,
2987 struct audio_mmap_buffer_info *info)
2988{
2989 struct stream_out *out = (struct stream_out *)stream;
2990 struct audio_device *adev = out->dev;
2991 int ret = 0;
2992 unsigned int offset1;
2993 unsigned int frames1;
2994 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002995 uint32_t mmap_size;
2996 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002997
2998 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08002999 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003000 pthread_mutex_lock(&adev->lock);
3001
3002 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003003 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003004 ret = -EINVAL;
3005 goto exit;
3006 }
3007 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003008 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003009 ret = -ENOSYS;
3010 goto exit;
3011 }
3012 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3013 if (out->pcm_device_id < 0) {
3014 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3015 __func__, out->pcm_device_id, out->usecase);
3016 ret = -EINVAL;
3017 goto exit;
3018 }
Phil Burkbc991042017-02-24 08:06:44 -08003019
3020 adjust_mmap_period_count(&out->config, min_size_frames);
3021
Eric Laurent0e46adf2016-12-16 12:49:24 -08003022 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3023 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3024 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3025 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3026 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3027 step = "open";
3028 ret = -ENODEV;
3029 goto exit;
3030 }
3031 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3032 if (ret < 0) {
3033 step = "begin";
3034 goto exit;
3035 }
3036 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003037 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003038 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003039 ret = platform_get_mmap_data_fd(adev->platform,
3040 out->pcm_device_id, 0 /*playback*/,
3041 &info->shared_memory_fd,
3042 &mmap_size);
3043 if (ret < 0) {
3044 // Fall back to non exclusive mode
3045 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3046 } else {
3047 if (mmap_size < buffer_size) {
3048 step = "mmap";
3049 goto exit;
3050 }
3051 // FIXME: indicate exclusive mode support by returning a negative buffer size
3052 info->buffer_size_frames *= -1;
3053 }
3054 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003055
3056 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3057 if (ret < 0) {
3058 step = "commit";
3059 goto exit;
3060 }
Phil Burkbc991042017-02-24 08:06:44 -08003061
3062 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003063 ret = 0;
3064
3065 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3066 __func__, info->shared_memory_address, info->buffer_size_frames);
3067
3068exit:
3069 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003070 if (out->pcm == NULL) {
3071 ALOGE("%s: %s - %d", __func__, step, ret);
3072 } else {
3073 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003074 pcm_close(out->pcm);
3075 out->pcm = NULL;
3076 }
3077 }
3078 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003079 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003080 return ret;
3081}
3082
3083static int out_get_mmap_position(const struct audio_stream_out *stream,
3084 struct audio_mmap_position *position)
3085{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003086 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003087 struct stream_out *out = (struct stream_out *)stream;
3088 ALOGVV("%s", __func__);
3089 if (position == NULL) {
3090 return -EINVAL;
3091 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003092 lock_output_stream(out);
3093 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3094 out->pcm == NULL) {
3095 ret = -ENOSYS;
3096 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003097 }
3098
3099 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003100 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003101 if (ret < 0) {
3102 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003103 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003104 }
Andy Hungfc044e12017-03-20 09:24:22 -07003105 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003106exit:
3107 pthread_mutex_unlock(&out->lock);
3108 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003109}
3110
3111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112/** audio_stream_in implementation **/
3113static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3114{
3115 struct stream_in *in = (struct stream_in *)stream;
3116
3117 return in->config.rate;
3118}
3119
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003120static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121{
3122 return -ENOSYS;
3123}
3124
3125static size_t in_get_buffer_size(const struct audio_stream *stream)
3126{
3127 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003128 return in->config.period_size * in->af_period_multiplier *
3129 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130}
3131
3132static uint32_t in_get_channels(const struct audio_stream *stream)
3133{
3134 struct stream_in *in = (struct stream_in *)stream;
3135
3136 return in->channel_mask;
3137}
3138
vivek mehta4ed66e62016-04-15 23:33:34 -07003139static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140{
vivek mehta4ed66e62016-04-15 23:33:34 -07003141 struct stream_in *in = (struct stream_in *)stream;
3142 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143}
3144
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003145static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146{
3147 return -ENOSYS;
3148}
3149
3150static int in_standby(struct audio_stream *stream)
3151{
3152 struct stream_in *in = (struct stream_in *)stream;
3153 struct audio_device *adev = in->dev;
3154 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003155 bool do_stop = true;
3156
Eric Laurent994a6932013-07-17 11:51:42 -07003157 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003158
3159 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003160
3161 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003162 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003163 audio_extn_sound_trigger_stop_lab(in);
3164 in->standby = true;
3165 }
3166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003168 if (adev->adm_deregister_stream)
3169 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3170
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003171 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003173 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003174 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003175 in->capture_started = false;
3176 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003177 if (in->pcm) {
3178 pcm_close(in->pcm);
3179 in->pcm = NULL;
3180 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003181 adev->enable_voicerx = false;
3182 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003183 if (do_stop) {
3184 status = stop_input_stream(in);
3185 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003186 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 }
3188 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003189 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 return status;
3191}
3192
Andy Hungd13f0d32017-06-12 13:58:37 -07003193static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194{
Andy Hungd13f0d32017-06-12 13:58:37 -07003195 struct stream_in *in = (struct stream_in *)stream;
3196
3197 // We try to get the lock for consistency,
3198 // but it isn't necessary for these variables.
3199 // If we're not in standby, we may be blocked on a read.
3200 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3201 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3202 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3203 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3204
3205 if (locked) {
3206 pthread_mutex_unlock(&in->lock);
3207 }
3208
3209 // dump error info
3210 (void)error_log_dump(
3211 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212 return 0;
3213}
3214
3215static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3216{
3217 struct stream_in *in = (struct stream_in *)stream;
3218 struct audio_device *adev = in->dev;
3219 struct str_parms *parms;
3220 char *str;
3221 char value[32];
3222 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003223 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224
Eric Laurent994a6932013-07-17 11:51:42 -07003225 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226 parms = str_parms_create_str(kvpairs);
3227
3228 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3229
Eric Laurenta1478072015-09-21 17:21:52 -07003230 lock_input_stream(in);
3231
Eric Laurent150dbfe2013-02-27 14:31:02 -08003232 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 if (ret >= 0) {
3234 val = atoi(value);
3235 /* no audio source uses val == 0 */
3236 if ((in->source != val) && (val != 0)) {
3237 in->source = val;
3238 }
3239 }
3240
3241 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003242
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243 if (ret >= 0) {
3244 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003245 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003246
3247 // Workaround: If routing to an non existing usb device, fail gracefully
3248 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003249 int card;
3250 if (audio_is_usb_in_device(val) &&
3251 (card = get_alive_usb_card(parms)) >= 0) {
3252
3253 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003254 status = -ENOSYS;
3255 } else {
3256
3257 in->device = val;
3258 /* If recording is in progress, change the tx device to new device */
3259 if (!in->standby) {
3260 ALOGV("update input routing change");
3261 // inform adm before actual routing to prevent glitches.
3262 if (adev->adm_on_routing_change) {
3263 adev->adm_on_routing_change(adev->adm_data,
3264 in->capture_handle);
3265 }
3266 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003267 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003268 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 }
3270 }
3271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003273 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274
3275 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003276 ALOGV("%s: exit: status(%d)", __func__, status);
3277 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278}
3279
Haynes Mathew George569b7482017-05-08 14:44:27 -07003280static char* in_get_parameters(const struct audio_stream *stream,
3281 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003283 struct stream_in *in = (struct stream_in *)stream;
3284 struct str_parms *query = str_parms_create_str(keys);
3285 char *str;
3286 struct str_parms *reply = str_parms_create();
3287 bool replied = false;
3288
3289 ALOGV("%s: enter: keys - %s", __func__, keys);
3290 replied |= stream_get_parameter_channels(query, reply,
3291 &in->supported_channel_masks[0]);
3292 replied |= stream_get_parameter_formats(query, reply,
3293 &in->supported_formats[0]);
3294 replied |= stream_get_parameter_rates(query, reply,
3295 &in->supported_sample_rates[0]);
3296 if (replied) {
3297 str = str_parms_to_str(reply);
3298 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003299 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003300 }
3301 str_parms_destroy(query);
3302 str_parms_destroy(reply);
3303 ALOGV("%s: exit: returns - %s", __func__, str);
3304 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305}
3306
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003307static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003309 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310}
3311
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003312static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3313{
3314 if (!stream || !parms)
3315 return;
3316
3317 struct stream_in *in = (struct stream_in *)stream;
3318 struct audio_device *adev = in->dev;
3319
3320 card_status_t status;
3321 int card;
3322 if (parse_snd_card_status(parms, &card, &status) < 0)
3323 return;
3324
3325 pthread_mutex_lock(&adev->lock);
3326 bool valid_cb = (card == adev->snd_card);
3327 pthread_mutex_unlock(&adev->lock);
3328
3329 if (!valid_cb)
3330 return;
3331
3332 lock_input_stream(in);
3333 if (in->card_status != status)
3334 in->card_status = status;
3335 pthread_mutex_unlock(&in->lock);
3336
3337 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3338 use_case_table[in->usecase],
3339 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3340
3341 // a better solution would be to report error back to AF and let
3342 // it put the stream to standby
3343 if (status == CARD_STATUS_OFFLINE)
3344 in_standby(&in->stream.common);
3345
3346 return;
3347}
3348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3350 size_t bytes)
3351{
3352 struct stream_in *in = (struct stream_in *)stream;
3353 struct audio_device *adev = in->dev;
3354 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003355 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003356 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357
Eric Laurenta1478072015-09-21 17:21:52 -07003358 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003359 const size_t frame_size = audio_stream_in_frame_size(stream);
3360 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003361
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003362 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003363 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003364 /* Read from sound trigger HAL */
3365 audio_extn_sound_trigger_read(in, buffer, bytes);
3366 pthread_mutex_unlock(&in->lock);
3367 return bytes;
3368 }
3369
Eric Laurent0e46adf2016-12-16 12:49:24 -08003370 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3371 ret = -ENOSYS;
3372 goto exit;
3373 }
3374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003376 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003378 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 goto exit;
3381 }
3382 in->standby = 0;
3383 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384
Andy Hungd13f0d32017-06-12 13:58:37 -07003385 // errors that occur here are read errors.
3386 error_code = ERROR_CODE_READ;
3387
Haynes Mathew George03c40102016-01-29 17:57:48 -08003388 //what's the duration requested by the client?
3389 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3390 in->config.rate;
3391 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003392
Haynes Mathew George03c40102016-01-29 17:57:48 -08003393 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003395 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003396 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003397 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003398 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003399 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003400 if (ret < 0) {
3401 ALOGE("Failed to read w/err %s", strerror(errno));
3402 ret = -errno;
3403 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003404 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3405 if (bytes % 4 == 0) {
3406 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3407 int_buf_stream = buffer;
3408 for (size_t itt=0; itt < bytes/4 ; itt++) {
3409 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003410 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003411 } else {
3412 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3413 ret = -EINVAL;
3414 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003415 }
3416 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 }
3418
Haynes Mathew George03c40102016-01-29 17:57:48 -08003419 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421 /*
3422 * Instead of writing zeroes here, we could trust the hardware
3423 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003424 * 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 -08003425 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003426 if (ret == 0 && adev->mic_muted &&
3427 !voice_is_in_call_rec_stream(in) &&
3428 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003430 in->frames_muted += frames;
3431 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432
3433exit:
3434 pthread_mutex_unlock(&in->lock);
3435
3436 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003437 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 in_standby(&in->stream.common);
3439 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003440 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003441 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003442 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003443 }
3444 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003445 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 }
3447 return bytes;
3448}
3449
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003450static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451{
3452 return 0;
3453}
3454
Andy Hung6ebe5962016-01-15 17:46:57 -08003455static int in_get_capture_position(const struct audio_stream_in *stream,
3456 int64_t *frames, int64_t *time)
3457{
3458 if (stream == NULL || frames == NULL || time == NULL) {
3459 return -EINVAL;
3460 }
3461 struct stream_in *in = (struct stream_in *)stream;
3462 int ret = -ENOSYS;
3463
3464 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003465 // note: ST sessions do not close the alsa pcm driver synchronously
3466 // on standby. Therefore, we may return an error even though the
3467 // pcm stream is still opened.
3468 if (in->standby) {
3469 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3470 "%s stream in standby but pcm not NULL for non ST session", __func__);
3471 goto exit;
3472 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003473 if (in->pcm) {
3474 struct timespec timestamp;
3475 unsigned int avail;
3476 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3477 *frames = in->frames_read + avail;
3478 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3479 ret = 0;
3480 }
3481 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003482exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003483 pthread_mutex_unlock(&in->lock);
3484 return ret;
3485}
3486
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003487static int add_remove_audio_effect(const struct audio_stream *stream,
3488 effect_handle_t effect,
3489 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003491 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003492 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003493 int status = 0;
3494 effect_descriptor_t desc;
3495
3496 status = (*effect)->get_descriptor(effect, &desc);
3497 if (status != 0)
3498 return status;
3499
Eric Laurenta1478072015-09-21 17:21:52 -07003500 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003501 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003502 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003503 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003504 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003505 in->enable_aec != enable &&
3506 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3507 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003508 if (!enable)
3509 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003510 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3511 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3512 adev->enable_voicerx = enable;
3513 struct audio_usecase *usecase;
3514 struct listnode *node;
3515 list_for_each(node, &adev->usecase_list) {
3516 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003517 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003518 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003519 }
3520 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003521 if (!in->standby)
3522 select_devices(in->dev, in->usecase);
3523 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003524 if (in->enable_ns != enable &&
3525 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3526 in->enable_ns = enable;
3527 if (!in->standby)
3528 select_devices(in->dev, in->usecase);
3529 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003530 pthread_mutex_unlock(&in->dev->lock);
3531 pthread_mutex_unlock(&in->lock);
3532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533 return 0;
3534}
3535
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003536static int in_add_audio_effect(const struct audio_stream *stream,
3537 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538{
Eric Laurent994a6932013-07-17 11:51:42 -07003539 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003540 return add_remove_audio_effect(stream, effect, true);
3541}
3542
3543static int in_remove_audio_effect(const struct audio_stream *stream,
3544 effect_handle_t effect)
3545{
Eric Laurent994a6932013-07-17 11:51:42 -07003546 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003547 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548}
3549
Eric Laurent0e46adf2016-12-16 12:49:24 -08003550static int in_stop(const struct audio_stream_in* stream)
3551{
3552 struct stream_in *in = (struct stream_in *)stream;
3553 struct audio_device *adev = in->dev;
3554
3555 int ret = -ENOSYS;
3556 ALOGV("%s", __func__);
3557 pthread_mutex_lock(&adev->lock);
3558 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3559 in->capture_started && in->pcm != NULL) {
3560 pcm_stop(in->pcm);
3561 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003562 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003563 }
3564 pthread_mutex_unlock(&adev->lock);
3565 return ret;
3566}
3567
3568static int in_start(const struct audio_stream_in* stream)
3569{
3570 struct stream_in *in = (struct stream_in *)stream;
3571 struct audio_device *adev = in->dev;
3572 int ret = -ENOSYS;
3573
3574 ALOGV("%s in %p", __func__, in);
3575 pthread_mutex_lock(&adev->lock);
3576 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3577 !in->capture_started && in->pcm != NULL) {
3578 if (!in->capture_started) {
3579 ret = start_input_stream(in);
3580 if (ret == 0) {
3581 in->capture_started = true;
3582 }
3583 }
3584 }
3585 pthread_mutex_unlock(&adev->lock);
3586 return ret;
3587}
3588
3589static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3590 int32_t min_size_frames,
3591 struct audio_mmap_buffer_info *info)
3592{
3593 struct stream_in *in = (struct stream_in *)stream;
3594 struct audio_device *adev = in->dev;
3595 int ret = 0;
3596 unsigned int offset1;
3597 unsigned int frames1;
3598 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003599 uint32_t mmap_size;
3600 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003601
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003602 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003603 pthread_mutex_lock(&adev->lock);
3604 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003605
Eric Laurent0e46adf2016-12-16 12:49:24 -08003606 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003607 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003608 ret = -EINVAL;
3609 goto exit;
3610 }
3611 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003612 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003613 ALOGV("%s in %p", __func__, in);
3614 ret = -ENOSYS;
3615 goto exit;
3616 }
3617 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3618 if (in->pcm_device_id < 0) {
3619 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3620 __func__, in->pcm_device_id, in->usecase);
3621 ret = -EINVAL;
3622 goto exit;
3623 }
Phil Burkbc991042017-02-24 08:06:44 -08003624
3625 adjust_mmap_period_count(&in->config, min_size_frames);
3626
Eric Laurent0e46adf2016-12-16 12:49:24 -08003627 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3628 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3629 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3630 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3631 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3632 step = "open";
3633 ret = -ENODEV;
3634 goto exit;
3635 }
3636
3637 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3638 if (ret < 0) {
3639 step = "begin";
3640 goto exit;
3641 }
3642 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003643 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003644 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003645 ret = platform_get_mmap_data_fd(adev->platform,
3646 in->pcm_device_id, 1 /*capture*/,
3647 &info->shared_memory_fd,
3648 &mmap_size);
3649 if (ret < 0) {
3650 // Fall back to non exclusive mode
3651 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3652 } else {
3653 if (mmap_size < buffer_size) {
3654 step = "mmap";
3655 goto exit;
3656 }
3657 // FIXME: indicate exclusive mode support by returning a negative buffer size
3658 info->buffer_size_frames *= -1;
3659 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003660
Haynes Mathew George96483a22017-03-28 14:52:47 -07003661 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003662
3663 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3664 if (ret < 0) {
3665 step = "commit";
3666 goto exit;
3667 }
3668
Phil Burkbc991042017-02-24 08:06:44 -08003669 in->standby = false;
3670 ret = 0;
3671
Eric Laurent0e46adf2016-12-16 12:49:24 -08003672 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3673 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003674
3675exit:
3676 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003677 if (in->pcm == NULL) {
3678 ALOGE("%s: %s - %d", __func__, step, ret);
3679 } else {
3680 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003681 pcm_close(in->pcm);
3682 in->pcm = NULL;
3683 }
3684 }
3685 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003686 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003687 return ret;
3688}
3689
3690static int in_get_mmap_position(const struct audio_stream_in *stream,
3691 struct audio_mmap_position *position)
3692{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003693 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003694 struct stream_in *in = (struct stream_in *)stream;
3695 ALOGVV("%s", __func__);
3696 if (position == NULL) {
3697 return -EINVAL;
3698 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003699 lock_input_stream(in);
3700 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3701 in->pcm == NULL) {
3702 ret = -ENOSYS;
3703 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003704 }
3705 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003706 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003707 if (ret < 0) {
3708 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003709 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003710 }
Andy Hungfc044e12017-03-20 09:24:22 -07003711 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003712exit:
3713 pthread_mutex_unlock(&in->lock);
3714 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003715}
3716
jiabin8962a4d2018-03-19 18:21:24 -07003717static int in_get_active_microphones(const struct audio_stream_in *stream,
3718 struct audio_microphone_characteristic_t *mic_array,
3719 size_t *mic_count) {
3720 struct stream_in *in = (struct stream_in *)stream;
3721 struct audio_device *adev = in->dev;
3722 ALOGVV("%s", __func__);
3723
3724 lock_input_stream(in);
3725 pthread_mutex_lock(&adev->lock);
3726 int ret = platform_get_active_microphones(adev->platform, in->device,
3727 audio_channel_count_from_in_mask(in->channel_mask),
3728 in->source, in->usecase, mic_array, mic_count);
3729 pthread_mutex_unlock(&adev->lock);
3730 pthread_mutex_unlock(&in->lock);
3731
3732 return ret;
3733}
3734
3735static int adev_get_microphones(const struct audio_hw_device *dev,
3736 struct audio_microphone_characteristic_t *mic_array,
3737 size_t *mic_count) {
3738 struct audio_device *adev = (struct audio_device *)dev;
3739 ALOGVV("%s", __func__);
3740
3741 pthread_mutex_lock(&adev->lock);
3742 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
3743 pthread_mutex_unlock(&adev->lock);
3744
3745 return ret;
3746}
Eric Laurent0e46adf2016-12-16 12:49:24 -08003747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748static int adev_open_output_stream(struct audio_hw_device *dev,
3749 audio_io_handle_t handle,
3750 audio_devices_t devices,
3751 audio_output_flags_t flags,
3752 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003753 struct audio_stream_out **stream_out,
3754 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755{
3756 struct audio_device *adev = (struct audio_device *)dev;
3757 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003758 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003759 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3760 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3761 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762
Andy Hungd9653bd2017-08-01 19:31:39 -07003763 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3764 return -ENOSYS;
3765 }
3766
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003767 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3768 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 *stream_out = NULL;
3770 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3771
3772 if (devices == AUDIO_DEVICE_NONE)
3773 devices = AUDIO_DEVICE_OUT_SPEAKER;
3774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 out->flags = flags;
3776 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003777 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003778 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003779 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780
3781 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003782 if ((is_hdmi || is_usb_dev) &&
3783 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3784 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3785 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003786 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003787 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003788 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003789 if (config->sample_rate == 0)
3790 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3791 if (config->channel_mask == 0)
3792 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3793 if (config->format == AUDIO_FORMAT_DEFAULT)
3794 config->format = AUDIO_FORMAT_PCM_16_BIT;
3795 } else if (is_usb_dev) {
3796 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3797 &config->format,
3798 &out->supported_formats[0],
3799 MAX_SUPPORTED_FORMATS,
3800 &config->channel_mask,
3801 &out->supported_channel_masks[0],
3802 MAX_SUPPORTED_CHANNEL_MASKS,
3803 &config->sample_rate,
3804 &out->supported_sample_rates[0],
3805 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003806 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003807 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003808 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003809 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003810 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003811
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003812
Haynes Mathew George569b7482017-05-08 14:44:27 -07003813 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003814 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003815 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003816 if (is_hdmi) {
3817 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3818 out->config = pcm_config_hdmi_multi;
3819 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3820 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3821 out->config = pcm_config_mmap_playback;
3822 out->stream.start = out_start;
3823 out->stream.stop = out_stop;
3824 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3825 out->stream.get_mmap_position = out_get_mmap_position;
3826 } else {
3827 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3828 out->config = pcm_config_hifi;
3829 }
3830
3831 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003832 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003833 if (is_hdmi) {
3834 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3835 audio_bytes_per_sample(out->format));
3836 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003837 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003838 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003839 pthread_mutex_lock(&adev->lock);
3840 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3841 pthread_mutex_unlock(&adev->lock);
3842
3843 // reject offload during card offline to allow
3844 // fallback to s/w paths
3845 if (offline) {
3846 ret = -ENODEV;
3847 goto error_open;
3848 }
3849
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003850 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3851 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3852 ALOGE("%s: Unsupported Offload information", __func__);
3853 ret = -EINVAL;
3854 goto error_open;
3855 }
3856 if (!is_supported_format(config->offload_info.format)) {
3857 ALOGE("%s: Unsupported audio format", __func__);
3858 ret = -EINVAL;
3859 goto error_open;
3860 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003861 out->sample_rate = config->offload_info.sample_rate;
3862 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
3863 out->channel_mask = config->offload_info.channel_mask;
3864 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
3865 out->channel_mask = config->channel_mask;
3866 else
3867 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3868
3869 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003870
3871 out->compr_config.codec = (struct snd_codec *)
3872 calloc(1, sizeof(struct snd_codec));
3873
3874 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003875
3876 out->stream.set_callback = out_set_callback;
3877 out->stream.pause = out_pause;
3878 out->stream.resume = out_resume;
3879 out->stream.drain = out_drain;
3880 out->stream.flush = out_flush;
3881
3882 out->compr_config.codec->id =
3883 get_snd_codec_id(config->offload_info.format);
3884 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3885 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003886 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003887 out->compr_config.codec->bit_rate =
3888 config->offload_info.bit_rate;
3889 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003890 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003891 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3892
3893 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3894 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003895
3896 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003897 create_offload_callback_thread(out);
3898 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3899 __func__, config->offload_info.version,
3900 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003901 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3902 switch (config->sample_rate) {
3903 case 0:
3904 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3905 break;
3906 case 8000:
3907 case 16000:
3908 case 48000:
3909 out->sample_rate = config->sample_rate;
3910 break;
3911 default:
3912 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
3913 config->sample_rate);
3914 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3915 ret = -EINVAL;
3916 goto error_open;
3917 }
3918 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3919 switch (config->channel_mask) {
3920 case AUDIO_CHANNEL_NONE:
3921 case AUDIO_CHANNEL_OUT_STEREO:
3922 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3923 break;
3924 default:
3925 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
3926 config->channel_mask);
3927 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3928 ret = -EINVAL;
3929 goto error_open;
3930 }
3931 switch (config->format) {
3932 case AUDIO_FORMAT_DEFAULT:
3933 case AUDIO_FORMAT_PCM_16_BIT:
3934 out->format = AUDIO_FORMAT_PCM_16_BIT;
3935 break;
3936 default:
3937 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
3938 config->format);
3939 config->format = AUDIO_FORMAT_PCM_16_BIT;
3940 ret = -EINVAL;
3941 goto error_open;
3942 }
3943
3944 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003945 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003946 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003947 case 0:
3948 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
3949 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07003950 case 8000:
3951 case 16000:
3952 case 48000:
3953 out->sample_rate = config->sample_rate;
3954 break;
3955 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003956 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
3957 config->sample_rate);
3958 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3959 ret = -EINVAL;
3960 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003961 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003962 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3963 switch (config->channel_mask) {
3964 case AUDIO_CHANNEL_NONE:
3965 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3966 break;
3967 case AUDIO_CHANNEL_OUT_STEREO:
3968 out->channel_mask = config->channel_mask;
3969 break;
3970 default:
3971 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
3972 config->channel_mask);
3973 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3974 ret = -EINVAL;
3975 break;
3976 }
3977 switch (config->format) {
3978 case AUDIO_FORMAT_DEFAULT:
3979 out->format = AUDIO_FORMAT_PCM_16_BIT;
3980 break;
3981 case AUDIO_FORMAT_PCM_16_BIT:
3982 out->format = config->format;
3983 break;
3984 default:
3985 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
3986 config->format);
3987 config->format = AUDIO_FORMAT_PCM_16_BIT;
3988 ret = -EINVAL;
3989 break;
3990 }
3991 if (ret != 0)
3992 goto error_open;
3993
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003994 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3995 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003996 out->config.rate = out->sample_rate;
3997 out->config.channels =
3998 audio_channel_count_from_out_mask(out->channel_mask);
3999 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004000 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004001 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4002 switch (config->sample_rate) {
4003 case 0:
4004 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4005 break;
4006 case 8000:
4007 case 16000:
4008 case 32000:
4009 case 48000:
4010 out->sample_rate = config->sample_rate;
4011 break;
4012 default:
4013 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4014 config->sample_rate);
4015 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4016 ret = -EINVAL;
4017 break;
4018 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004019 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004020 switch (config->channel_mask) {
4021 case AUDIO_CHANNEL_NONE:
4022 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4023 break;
4024 case AUDIO_CHANNEL_OUT_STEREO:
4025 out->channel_mask = config->channel_mask;
4026 break;
4027 default:
4028 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4029 config->channel_mask);
4030 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4031 ret = -EINVAL;
4032 break;
4033 }
4034 switch (config->format) {
4035 case AUDIO_FORMAT_DEFAULT:
4036 out->format = AUDIO_FORMAT_PCM_16_BIT;
4037 break;
4038 case AUDIO_FORMAT_PCM_16_BIT:
4039 out->format = config->format;
4040 break;
4041 default:
4042 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4043 config->format);
4044 config->format = AUDIO_FORMAT_PCM_16_BIT;
4045 ret = -EINVAL;
4046 break;
4047 }
4048 if (ret != 0)
4049 goto error_open;
4050
vivek mehtaa68fea62017-06-08 19:04:02 -07004051 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004052 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4053 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004054 out->config.rate = out->sample_rate;
4055 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004056 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004057 out->sample_rate,
4058 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004059 out->config.channels,
4060 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004061 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004062 out->config.period_size = buffer_size / frame_size;
4063 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4064 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004066 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004067 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4068 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004069 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004070 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4071 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004072 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004073 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004074 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004075 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004076 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004077 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4078 out->config = pcm_config_mmap_playback;
4079 out->stream.start = out_start;
4080 out->stream.stop = out_stop;
4081 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4082 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004083 } else {
4084 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4085 out->config = pcm_config_low_latency;
4086 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004087
4088 if (config->sample_rate == 0) {
4089 out->sample_rate = out->config.rate;
4090 } else {
4091 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004092 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004093 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4094 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4095 } else {
4096 out->channel_mask = config->channel_mask;
4097 }
4098 if (config->format == AUDIO_FORMAT_DEFAULT)
4099 out->format = audio_format_from_pcm_format(out->config.format);
4100 else if (!audio_is_linear_pcm(config->format)) {
4101 config->format = AUDIO_FORMAT_PCM_16_BIT;
4102 ret = -EINVAL;
4103 goto error_open;
4104 } else {
4105 out->format = config->format;
4106 }
4107
4108 out->config.rate = out->sample_rate;
4109 out->config.channels =
4110 audio_channel_count_from_out_mask(out->channel_mask);
4111 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4112 out->config.format = pcm_format_from_audio_format(out->format);
4113 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004115
4116 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4117 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004118 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004119 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4120 __func__, config->sample_rate, config->format, config->channel_mask);
4121 config->sample_rate = out->sample_rate;
4122 config->format = out->format;
4123 config->channel_mask = out->channel_mask;
4124 ret = -EINVAL;
4125 goto error_open;
4126 }
4127
Andy Hung6fcba9c2014-03-18 11:53:32 -07004128 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4129 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004131 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004132 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004133 adev->primary_output = out;
4134 else {
4135 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004136 ret = -EEXIST;
4137 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004138 }
4139 }
4140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004141 /* Check if this usecase is already existing */
4142 pthread_mutex_lock(&adev->lock);
4143 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4144 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004146 ret = -EEXIST;
4147 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004148 }
4149 pthread_mutex_unlock(&adev->lock);
4150
4151 out->stream.common.get_sample_rate = out_get_sample_rate;
4152 out->stream.common.set_sample_rate = out_set_sample_rate;
4153 out->stream.common.get_buffer_size = out_get_buffer_size;
4154 out->stream.common.get_channels = out_get_channels;
4155 out->stream.common.get_format = out_get_format;
4156 out->stream.common.set_format = out_set_format;
4157 out->stream.common.standby = out_standby;
4158 out->stream.common.dump = out_dump;
4159 out->stream.common.set_parameters = out_set_parameters;
4160 out->stream.common.get_parameters = out_get_parameters;
4161 out->stream.common.add_audio_effect = out_add_audio_effect;
4162 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4163 out->stream.get_latency = out_get_latency;
4164 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004165#ifdef NO_AUDIO_OUT
4166 out->stream.write = out_write_for_no_output;
4167#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004168 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004169#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170 out->stream.get_render_position = out_get_render_position;
4171 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004172 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173
Eric Laurent0e46adf2016-12-16 12:49:24 -08004174 if (out->realtime)
4175 out->af_period_multiplier = af_period_multiplier;
4176 else
4177 out->af_period_multiplier = 1;
4178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004180 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004181 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004183 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004184 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004185 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004187 config->format = out->stream.common.get_format(&out->stream.common);
4188 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4189 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4190
Andy Hunga452b0a2017-03-15 14:51:15 -07004191 out->error_log = error_log_create(
4192 ERROR_LOG_ENTRIES,
4193 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4194
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004195 /*
4196 By locking output stream before registering, we allow the callback
4197 to update stream's state only after stream's initial state is set to
4198 adev state.
4199 */
4200 lock_output_stream(out);
4201 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4202 pthread_mutex_lock(&adev->lock);
4203 out->card_status = adev->card_status;
4204 pthread_mutex_unlock(&adev->lock);
4205 pthread_mutex_unlock(&out->lock);
4206
vivek mehta4a824772017-06-08 19:05:49 -07004207 stream_app_type_cfg_init(&out->app_type_cfg);
4208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004210
Eric Laurent994a6932013-07-17 11:51:42 -07004211 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004213
4214error_open:
4215 free(out);
4216 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004217 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004218 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219}
4220
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004221static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222 struct audio_stream_out *stream)
4223{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004224 struct stream_out *out = (struct stream_out *)stream;
4225 struct audio_device *adev = out->dev;
4226
Eric Laurent994a6932013-07-17 11:51:42 -07004227 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004228
4229 // must deregister from sndmonitor first to prevent races
4230 // between the callback and close_stream
4231 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004233 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4234 destroy_offload_callback_thread(out);
4235
4236 if (out->compr_config.codec != NULL)
4237 free(out->compr_config.codec);
4238 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004239
4240 if (adev->voice_tx_output == out)
4241 adev->voice_tx_output = NULL;
4242
Andy Hunga452b0a2017-03-15 14:51:15 -07004243 error_log_destroy(out->error_log);
4244 out->error_log = NULL;
4245
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004246 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004247 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004248 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004249 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004250 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251}
4252
4253static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4254{
4255 struct audio_device *adev = (struct audio_device *)dev;
4256 struct str_parms *parms;
4257 char *str;
4258 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004259 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004260 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004261 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262
Joe Onorato188b6222016-03-01 11:02:27 -08004263 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004264
4265 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004266
4267 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004268 status = voice_set_parameters(adev, parms);
4269 if (status != 0) {
4270 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004271 }
4272
4273 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4274 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004275 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4277 adev->bluetooth_nrec = true;
4278 else
4279 adev->bluetooth_nrec = false;
4280 }
4281
4282 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4283 if (ret >= 0) {
4284 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4285 adev->screen_off = false;
4286 else
4287 adev->screen_off = true;
4288 }
4289
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004290 ret = str_parms_get_int(parms, "rotation", &val);
4291 if (ret >= 0) {
4292 bool reverse_speakers = false;
4293 switch(val) {
4294 // FIXME: note that the code below assumes that the speakers are in the correct placement
4295 // relative to the user when the device is rotated 90deg from its default rotation. This
4296 // assumption is device-specific, not platform-specific like this code.
4297 case 270:
4298 reverse_speakers = true;
4299 break;
4300 case 0:
4301 case 90:
4302 case 180:
4303 break;
4304 default:
4305 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004306 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004307 }
Eric Laurent03f09432014-03-25 18:09:11 -07004308 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004309 // check and set swap
4310 // - check if orientation changed and speaker active
4311 // - set rotation and cache the rotation value
4312 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004313 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004314 }
4315
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004316 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4317 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004318 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004319 }
4320
David Linee3fe402017-03-13 10:00:42 -07004321 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4322 if (ret >= 0) {
4323 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004324 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004325 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4326 if (ret >= 0) {
4327 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004328 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004329 }
Eric Laurent99dab492017-06-17 15:19:08 -07004330 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004331 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4332 if (ret >= 0) {
4333 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004334 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004335 }
4336 }
4337 }
4338
4339 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4340 if (ret >= 0) {
4341 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004342 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004343 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4344 if (ret >= 0) {
4345 const int card = atoi(value);
4346
Eric Laurent99dab492017-06-17 15:19:08 -07004347 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004348 }
Eric Laurent99dab492017-06-17 15:19:08 -07004349 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004350 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4351 if (ret >= 0) {
4352 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004353 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004354 }
4355 }
4356 }
4357
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004358 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004359done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004361 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004362 ALOGV("%s: exit with code(%d)", __func__, status);
4363 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004364}
4365
4366static char* adev_get_parameters(const struct audio_hw_device *dev,
4367 const char *keys)
4368{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004369 struct audio_device *adev = (struct audio_device *)dev;
4370 struct str_parms *reply = str_parms_create();
4371 struct str_parms *query = str_parms_create_str(keys);
4372 char *str;
4373
4374 pthread_mutex_lock(&adev->lock);
4375
4376 voice_get_parameters(adev, query, reply);
4377 str = str_parms_to_str(reply);
4378 str_parms_destroy(query);
4379 str_parms_destroy(reply);
4380
4381 pthread_mutex_unlock(&adev->lock);
4382 ALOGV("%s: exit: returns - %s", __func__, str);
4383 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384}
4385
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004386static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387{
4388 return 0;
4389}
4390
Haynes Mathew George5191a852013-09-11 14:19:36 -07004391static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4392{
4393 int ret;
4394 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004395
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004396 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4397
Haynes Mathew George5191a852013-09-11 14:19:36 -07004398 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004399 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004400 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004401
Haynes Mathew George5191a852013-09-11 14:19:36 -07004402 return ret;
4403}
4404
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004405static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004406{
4407 return -ENOSYS;
4408}
4409
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004410static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4411 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412{
4413 return -ENOSYS;
4414}
4415
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004416static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004417{
4418 return -ENOSYS;
4419}
4420
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004421static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422{
4423 return -ENOSYS;
4424}
4425
4426static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4427{
4428 struct audio_device *adev = (struct audio_device *)dev;
4429
4430 pthread_mutex_lock(&adev->lock);
4431 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004432 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004433 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004434 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4435 voice_is_in_call(adev)) {
4436 voice_stop_call(adev);
4437 adev->current_call_output = NULL;
4438 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004439 }
4440 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004441
4442 audio_extn_extspk_set_mode(adev->extspk, mode);
4443
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444 return 0;
4445}
4446
4447static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4448{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004449 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004450 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004451
Eric Laurent2bafff12016-03-17 12:17:23 -07004452 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004453 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004454 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4455 ret = audio_extn_hfp_set_mic_mute(adev, state);
4456 } else {
4457 ret = voice_set_mic_mute(adev, state);
4458 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004459 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004460 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004461
4462 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004463}
4464
4465static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4466{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004467 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004468 return 0;
4469}
4470
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004471static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004472 const struct audio_config *config)
4473{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004474 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475
Eric Laurent74b55762017-07-09 17:04:53 -07004476 /* Don't know if USB HIFI in this context so use true to be conservative */
4477 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4478 true /*is_usb_hifi */) != 0)
4479 return 0;
4480
vivek mehtaa68fea62017-06-08 19:04:02 -07004481 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4482 config->sample_rate, config->format,
4483 channel_count,
4484 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004485}
4486
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004487static bool adev_input_allow_hifi_record(struct audio_device *adev,
4488 audio_devices_t devices,
4489 audio_input_flags_t flags,
4490 audio_source_t source) {
4491 const bool allowed = true;
4492
4493 if (!audio_is_usb_in_device(devices))
4494 return !allowed;
4495
4496 switch (flags) {
4497 case AUDIO_INPUT_FLAG_NONE:
4498 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4499 break;
4500 default:
4501 return !allowed;
4502 }
4503
4504 switch (source) {
4505 case AUDIO_SOURCE_DEFAULT:
4506 case AUDIO_SOURCE_MIC:
4507 case AUDIO_SOURCE_UNPROCESSED:
4508 break;
4509 default:
4510 return !allowed;
4511 }
4512
4513 switch (adev->mode) {
4514 case 0:
4515 break;
4516 default:
4517 return !allowed;
4518 }
4519
4520 return allowed;
4521}
4522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004523static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004524 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004525 audio_devices_t devices,
4526 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004527 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004528 audio_input_flags_t flags,
4529 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004530 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531{
4532 struct audio_device *adev = (struct audio_device *)dev;
4533 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004534 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004535 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004536 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004537 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004538 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4539 devices,
4540 flags,
4541 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004542 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004543 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004544
Andy Hungd9653bd2017-08-01 19:31:39 -07004545 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4546 return -ENOSYS;
4547 }
4548
Eric Laurent74b55762017-07-09 17:04:53 -07004549 if (!(is_usb_dev && may_use_hifi_record)) {
4550 if (config->sample_rate == 0)
4551 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4552 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4553 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4554 if (config->format == AUDIO_FORMAT_DEFAULT)
4555 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004556
Eric Laurent74b55762017-07-09 17:04:53 -07004557 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4558
4559 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4560 return -EINVAL;
4561 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004563 if (audio_extn_tfa_98xx_is_supported() &&
4564 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004565 return -EINVAL;
4566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004567 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4568
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004569 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004570 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572 in->stream.common.get_sample_rate = in_get_sample_rate;
4573 in->stream.common.set_sample_rate = in_set_sample_rate;
4574 in->stream.common.get_buffer_size = in_get_buffer_size;
4575 in->stream.common.get_channels = in_get_channels;
4576 in->stream.common.get_format = in_get_format;
4577 in->stream.common.set_format = in_set_format;
4578 in->stream.common.standby = in_standby;
4579 in->stream.common.dump = in_dump;
4580 in->stream.common.set_parameters = in_set_parameters;
4581 in->stream.common.get_parameters = in_get_parameters;
4582 in->stream.common.add_audio_effect = in_add_audio_effect;
4583 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4584 in->stream.set_gain = in_set_gain;
4585 in->stream.read = in_read;
4586 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004587 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07004588 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589
4590 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004591 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004594 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004595 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004596
Haynes Mathew George569b7482017-05-08 14:44:27 -07004597 if (is_usb_dev && may_use_hifi_record) {
4598 /* HiFi record selects an appropriate format, channel, rate combo
4599 depending on sink capabilities*/
4600 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4601 &config->format,
4602 &in->supported_formats[0],
4603 MAX_SUPPORTED_FORMATS,
4604 &config->channel_mask,
4605 &in->supported_channel_masks[0],
4606 MAX_SUPPORTED_CHANNEL_MASKS,
4607 &config->sample_rate,
4608 &in->supported_sample_rates[0],
4609 MAX_SUPPORTED_SAMPLE_RATES);
4610 if (ret != 0) {
4611 ret = -EINVAL;
4612 goto err_open;
4613 }
Eric Laurent74b55762017-07-09 17:04:53 -07004614 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004615 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004616 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004617 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4618 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4619 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4620 bool ret_error = false;
4621 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4622 from HAL is 8_24
4623 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4624 8_24 return error indicating supported format is 8_24
4625 *> In case of any other source requesting 24 bit or float return error
4626 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004627
vivek mehta57ff9b52016-04-28 14:13:08 -07004628 on error flinger will retry with supported format passed
4629 */
4630 if (source != AUDIO_SOURCE_UNPROCESSED) {
4631 config->format = AUDIO_FORMAT_PCM_16_BIT;
4632 ret_error = true;
4633 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4634 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4635 ret_error = true;
4636 }
4637
4638 if (ret_error) {
4639 ret = -EINVAL;
4640 goto err_open;
4641 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004642 }
4643
vivek mehta57ff9b52016-04-28 14:13:08 -07004644 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004645 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004648 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4649 if (config->sample_rate == 0)
4650 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4651 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4652 config->sample_rate != 8000) {
4653 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4654 ret = -EINVAL;
4655 goto err_open;
4656 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004657
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004658 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4659 config->format = AUDIO_FORMAT_PCM_16_BIT;
4660 ret = -EINVAL;
4661 goto err_open;
4662 }
4663
4664 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4665 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004666 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004667 } else if (is_usb_dev && may_use_hifi_record) {
4668 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4669 in->config = pcm_config_audio_capture;
4670 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004671 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4672 config->sample_rate,
4673 config->format,
4674 channel_count,
4675 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004676 in->config.period_size = buffer_size / frame_size;
4677 in->config.rate = config->sample_rate;
4678 in->af_period_multiplier = 1;
4679 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004680 } else {
4681 in->usecase = USECASE_AUDIO_RECORD;
4682 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004683 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004684 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004685#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004686 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004687#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004688 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004689 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004690 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004691 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004692 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4693 config->sample_rate,
4694 config->format,
4695 channel_count,
4696 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004697 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004698 in->config.rate = config->sample_rate;
4699 in->af_period_multiplier = 1;
4700 } else {
4701 // period size is left untouched for rt mode playback
4702 in->config = pcm_config_audio_capture_rt;
4703 in->af_period_multiplier = af_period_multiplier;
4704 }
4705 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4706 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004707 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004708 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4709 in->config = pcm_config_mmap_capture;
4710 in->stream.start = in_start;
4711 in->stream.stop = in_stop;
4712 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4713 in->stream.get_mmap_position = in_get_mmap_position;
4714 in->af_period_multiplier = 1;
4715 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004716 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004717 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004718 (config->sample_rate == 8000 ||
4719 config->sample_rate == 16000 ||
4720 config->sample_rate == 32000 ||
4721 config->sample_rate == 48000) &&
4722 channel_count == 1) {
4723 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4724 in->config = pcm_config_audio_capture;
4725 frame_size = audio_stream_in_frame_size(&in->stream);
4726 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4727 config->sample_rate,
4728 config->format,
4729 channel_count, false /*is_low_latency*/);
4730 in->config.period_size = buffer_size / frame_size;
4731 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4732 in->config.rate = config->sample_rate;
4733 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004734 } else {
4735 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004736 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004737 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4738 config->sample_rate,
4739 config->format,
4740 channel_count,
4741 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004742 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004743 in->config.rate = config->sample_rate;
4744 in->af_period_multiplier = 1;
4745 }
4746 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4747 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004748 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004750 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004751 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004752
Andy Hungd13f0d32017-06-12 13:58:37 -07004753 in->error_log = error_log_create(
4754 ERROR_LOG_ENTRIES,
4755 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4756
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004757 /* This stream could be for sound trigger lab,
4758 get sound trigger pcm if present */
4759 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004761 lock_input_stream(in);
4762 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4763 pthread_mutex_lock(&adev->lock);
4764 in->card_status = adev->card_status;
4765 pthread_mutex_unlock(&adev->lock);
4766 pthread_mutex_unlock(&in->lock);
4767
vivek mehta4a824772017-06-08 19:05:49 -07004768 stream_app_type_cfg_init(&in->app_type_cfg);
4769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004770 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004771 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772 return 0;
4773
4774err_open:
4775 free(in);
4776 *stream_in = NULL;
4777 return ret;
4778}
4779
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004780static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781 struct audio_stream_in *stream)
4782{
Andy Hungd13f0d32017-06-12 13:58:37 -07004783 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004784 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004785
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004786 // must deregister from sndmonitor first to prevent races
4787 // between the callback and close_stream
4788 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004789 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004790
4791 error_log_destroy(in->error_log);
4792 in->error_log = NULL;
4793
Andy Hung0dbb52b2017-08-09 13:51:38 -07004794 pthread_mutex_destroy(&in->pre_lock);
4795 pthread_mutex_destroy(&in->lock);
4796
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004797 free(stream);
4798
4799 return;
4800}
4801
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004802static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004803{
4804 return 0;
4805}
4806
Andy Hung31aca912014-03-20 17:14:59 -07004807/* verifies input and output devices and their capabilities.
4808 *
4809 * This verification is required when enabling extended bit-depth or
4810 * sampling rates, as not all qcom products support it.
4811 *
4812 * Suitable for calling only on initialization such as adev_open().
4813 * It fills the audio_device use_case_table[] array.
4814 *
4815 * Has a side-effect that it needs to configure audio routing / devices
4816 * in order to power up the devices and read the device parameters.
4817 * It does not acquire any hw device lock. Should restore the devices
4818 * back to "normal state" upon completion.
4819 */
4820static int adev_verify_devices(struct audio_device *adev)
4821{
4822 /* enumeration is a bit difficult because one really wants to pull
4823 * the use_case, device id, etc from the hidden pcm_device_table[].
4824 * In this case there are the following use cases and device ids.
4825 *
4826 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4827 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004828 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004829 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4830 * [USECASE_AUDIO_RECORD] = {0, 0},
4831 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4832 * [USECASE_VOICE_CALL] = {2, 2},
4833 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004834 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004835 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4836 */
4837
4838 /* should be the usecases enabled in adev_open_input_stream() */
4839 static const int test_in_usecases[] = {
4840 USECASE_AUDIO_RECORD,
4841 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4842 };
4843 /* should be the usecases enabled in adev_open_output_stream()*/
4844 static const int test_out_usecases[] = {
4845 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4846 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4847 };
4848 static const usecase_type_t usecase_type_by_dir[] = {
4849 PCM_PLAYBACK,
4850 PCM_CAPTURE,
4851 };
4852 static const unsigned flags_by_dir[] = {
4853 PCM_OUT,
4854 PCM_IN,
4855 };
4856
4857 size_t i;
4858 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004859 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004860 char info[512]; /* for possible debug info */
4861
4862 for (dir = 0; dir < 2; ++dir) {
4863 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4864 const unsigned flags_dir = flags_by_dir[dir];
4865 const size_t testsize =
4866 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4867 const int *testcases =
4868 dir ? test_in_usecases : test_out_usecases;
4869 const audio_devices_t audio_device =
4870 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4871
4872 for (i = 0; i < testsize; ++i) {
4873 const audio_usecase_t audio_usecase = testcases[i];
4874 int device_id;
4875 snd_device_t snd_device;
4876 struct pcm_params **pparams;
4877 struct stream_out out;
4878 struct stream_in in;
4879 struct audio_usecase uc_info;
4880 int retval;
4881
4882 pparams = &adev->use_case_table[audio_usecase];
4883 pcm_params_free(*pparams); /* can accept null input */
4884 *pparams = NULL;
4885
4886 /* find the device ID for the use case (signed, for error) */
4887 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4888 if (device_id < 0)
4889 continue;
4890
4891 /* prepare structures for device probing */
4892 memset(&uc_info, 0, sizeof(uc_info));
4893 uc_info.id = audio_usecase;
4894 uc_info.type = usecase_type;
4895 if (dir) {
4896 adev->active_input = &in;
4897 memset(&in, 0, sizeof(in));
4898 in.device = audio_device;
4899 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4900 uc_info.stream.in = &in;
4901 } else {
4902 adev->active_input = NULL;
4903 }
4904 memset(&out, 0, sizeof(out));
4905 out.devices = audio_device; /* only field needed in select_devices */
4906 uc_info.stream.out = &out;
4907 uc_info.devices = audio_device;
4908 uc_info.in_snd_device = SND_DEVICE_NONE;
4909 uc_info.out_snd_device = SND_DEVICE_NONE;
4910 list_add_tail(&adev->usecase_list, &uc_info.list);
4911
4912 /* select device - similar to start_(in/out)put_stream() */
4913 retval = select_devices(adev, audio_usecase);
4914 if (retval >= 0) {
4915 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4916#if LOG_NDEBUG == 0
4917 if (*pparams) {
4918 ALOGV("%s: (%s) card %d device %d", __func__,
4919 dir ? "input" : "output", card_id, device_id);
4920 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004921 } else {
4922 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4923 }
4924#endif
4925 }
4926
4927 /* deselect device - similar to stop_(in/out)put_stream() */
4928 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004929 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004930 /* 2. Disable the rx device */
4931 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004932 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004933 list_remove(&uc_info.list);
4934 }
4935 }
4936 adev->active_input = NULL; /* restore adev state */
4937 return 0;
4938}
4939
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004940static int adev_close(hw_device_t *device)
4941{
Andy Hung31aca912014-03-20 17:14:59 -07004942 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004943 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004944
4945 if (!adev)
4946 return 0;
4947
4948 pthread_mutex_lock(&adev_init_lock);
4949
4950 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004951 audio_extn_snd_mon_unregister_listener(adev);
4952 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004953 audio_route_free(adev->audio_route);
4954 free(adev->snd_dev_ref_cnt);
4955 platform_deinit(adev->platform);
4956 audio_extn_extspk_deinit(adev->extspk);
4957 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004958 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004959 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4960 pcm_params_free(adev->use_case_table[i]);
4961 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004962 if (adev->adm_deinit)
4963 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004964 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004965 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004966 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004967
4968 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004970 return 0;
4971}
4972
Glenn Kasten4f993392014-05-14 07:30:48 -07004973/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4974 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4975 * just that it _might_ work.
4976 */
4977static int period_size_is_plausible_for_low_latency(int period_size)
4978{
4979 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004980 case 48:
4981 case 96:
4982 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004983 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004984 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004985 case 240:
4986 case 320:
4987 case 480:
4988 return 1;
4989 default:
4990 return 0;
4991 }
4992}
4993
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004994static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4995{
4996 int card;
4997 card_status_t status;
4998
4999 if (!parms)
5000 return;
5001
5002 if (parse_snd_card_status(parms, &card, &status) < 0)
5003 return;
5004
5005 pthread_mutex_lock(&adev->lock);
5006 bool valid_cb = (card == adev->snd_card);
5007 if (valid_cb) {
5008 if (adev->card_status != status) {
5009 adev->card_status = status;
5010 platform_snd_card_update(adev->platform, status);
5011 }
5012 }
5013 pthread_mutex_unlock(&adev->lock);
5014 return;
5015}
5016
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005017static int adev_open(const hw_module_t *module, const char *name,
5018 hw_device_t **device)
5019{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005020 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005021
Eric Laurent2bafff12016-03-17 12:17:23 -07005022 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005023 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005024 pthread_mutex_lock(&adev_init_lock);
5025 if (audio_device_ref_count != 0) {
5026 *device = &adev->device.common;
5027 audio_device_ref_count++;
5028 ALOGV("%s: returning existing instance of adev", __func__);
5029 ALOGV("%s: exit", __func__);
5030 pthread_mutex_unlock(&adev_init_lock);
5031 return 0;
5032 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005033 adev = calloc(1, sizeof(struct audio_device));
5034
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005035 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005037 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5038 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5039 adev->device.common.module = (struct hw_module_t *)module;
5040 adev->device.common.close = adev_close;
5041
5042 adev->device.init_check = adev_init_check;
5043 adev->device.set_voice_volume = adev_set_voice_volume;
5044 adev->device.set_master_volume = adev_set_master_volume;
5045 adev->device.get_master_volume = adev_get_master_volume;
5046 adev->device.set_master_mute = adev_set_master_mute;
5047 adev->device.get_master_mute = adev_get_master_mute;
5048 adev->device.set_mode = adev_set_mode;
5049 adev->device.set_mic_mute = adev_set_mic_mute;
5050 adev->device.get_mic_mute = adev_get_mic_mute;
5051 adev->device.set_parameters = adev_set_parameters;
5052 adev->device.get_parameters = adev_get_parameters;
5053 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5054 adev->device.open_output_stream = adev_open_output_stream;
5055 adev->device.close_output_stream = adev_close_output_stream;
5056 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005058 adev->device.close_input_stream = adev_close_input_stream;
5059 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005060 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005061
5062 /* Set the default route before the PCM stream is opened */
5063 pthread_mutex_lock(&adev->lock);
5064 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005065 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005066 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005067 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005068 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005069 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005070 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005071 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005072 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005073 pthread_mutex_unlock(&adev->lock);
5074
5075 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005076 adev->platform = platform_init(adev);
5077 if (!adev->platform) {
5078 free(adev->snd_dev_ref_cnt);
5079 free(adev);
5080 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5081 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005082 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005083 return -EINVAL;
5084 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005085 adev->extspk = audio_extn_extspk_init(adev);
5086
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005087 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5088 if (adev->visualizer_lib == NULL) {
5089 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5090 } else {
5091 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5092 adev->visualizer_start_output =
5093 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5094 "visualizer_hal_start_output");
5095 adev->visualizer_stop_output =
5096 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5097 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005098 }
5099
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005100 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5101 if (adev->offload_effects_lib == NULL) {
5102 ALOGW("%s: DLOPEN failed for %s", __func__,
5103 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5104 } else {
5105 ALOGV("%s: DLOPEN successful for %s", __func__,
5106 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5107 adev->offload_effects_start_output =
5108 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5109 "offload_effects_bundle_hal_start_output");
5110 adev->offload_effects_stop_output =
5111 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5112 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005113 }
5114
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005115 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5116 if (adev->adm_lib == NULL) {
5117 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5118 } else {
5119 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5120 adev->adm_init = (adm_init_t)
5121 dlsym(adev->adm_lib, "adm_init");
5122 adev->adm_deinit = (adm_deinit_t)
5123 dlsym(adev->adm_lib, "adm_deinit");
5124 adev->adm_register_input_stream = (adm_register_input_stream_t)
5125 dlsym(adev->adm_lib, "adm_register_input_stream");
5126 adev->adm_register_output_stream = (adm_register_output_stream_t)
5127 dlsym(adev->adm_lib, "adm_register_output_stream");
5128 adev->adm_deregister_stream = (adm_deregister_stream_t)
5129 dlsym(adev->adm_lib, "adm_deregister_stream");
5130 adev->adm_request_focus = (adm_request_focus_t)
5131 dlsym(adev->adm_lib, "adm_request_focus");
5132 adev->adm_abandon_focus = (adm_abandon_focus_t)
5133 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005134 adev->adm_set_config = (adm_set_config_t)
5135 dlsym(adev->adm_lib, "adm_set_config");
5136 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5137 dlsym(adev->adm_lib, "adm_request_focus_v2");
5138 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5139 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5140 adev->adm_on_routing_change = (adm_on_routing_change_t)
5141 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005142 }
5143
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005144 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005145 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005147 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005148
Andy Hung31aca912014-03-20 17:14:59 -07005149 if (k_enable_extended_precision)
5150 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005151
Glenn Kasten4f993392014-05-14 07:30:48 -07005152 char value[PROPERTY_VALUE_MAX];
5153 int trial;
5154 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5155 trial = atoi(value);
5156 if (period_size_is_plausible_for_low_latency(trial)) {
5157 pcm_config_low_latency.period_size = trial;
5158 pcm_config_low_latency.start_threshold = trial / 4;
5159 pcm_config_low_latency.avail_min = trial / 4;
5160 configured_low_latency_capture_period_size = trial;
5161 }
5162 }
5163 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5164 trial = atoi(value);
5165 if (period_size_is_plausible_for_low_latency(trial)) {
5166 configured_low_latency_capture_period_size = trial;
5167 }
5168 }
5169
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005170 // commented as full set of app type cfg is sent from platform
5171 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005172 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005173
5174 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5175 af_period_multiplier = atoi(value);
5176 if (af_period_multiplier < 0) {
5177 af_period_multiplier = 2;
5178 } else if (af_period_multiplier > 4) {
5179 af_period_multiplier = 4;
5180 }
5181 ALOGV("new period_multiplier = %d", af_period_multiplier);
5182 }
5183
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005184 audio_extn_tfa_98xx_init(adev);
5185
vivek mehta1a9b7c02015-06-25 11:49:38 -07005186 pthread_mutex_unlock(&adev_init_lock);
5187
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005188 if (adev->adm_init)
5189 adev->adm_data = adev->adm_init();
5190
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005191 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005192 audio_extn_snd_mon_init();
5193 pthread_mutex_lock(&adev->lock);
5194 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5195 adev->card_status = CARD_STATUS_ONLINE;
5196 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005197 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005198
Eric Laurent2bafff12016-03-17 12:17:23 -07005199 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005200 return 0;
5201}
5202
5203static struct hw_module_methods_t hal_module_methods = {
5204 .open = adev_open,
5205};
5206
5207struct audio_module HAL_MODULE_INFO_SYM = {
5208 .common = {
5209 .tag = HARDWARE_MODULE_TAG,
5210 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5211 .hal_api_version = HARDWARE_HAL_API_VERSION,
5212 .id = AUDIO_HARDWARE_MODULE_ID,
5213 .name = "QCOM Audio HAL",
5214 .author = "Code Aurora Forum",
5215 .methods = &hal_module_methods,
5216 },
5217};