blob: ee25242b58fc99f0e4e9c257c3910cdcdc1155c7 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
52#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070076#define PROXY_OPEN_RETRY_COUNT 100
77#define PROXY_OPEN_WAIT_TIME 20
78
vivek mehtadae44712015-07-27 14:13:18 -070079#define MIN_CHANNEL_COUNT 1
80#define DEFAULT_CHANNEL_COUNT 2
81
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
83#define MAX_CHANNEL_COUNT 1
84#else
vivek mehtadae44712015-07-27 14:13:18 -070085#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
86#define XSTR(x) STR(x)
87#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#endif
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
102
Andy Hung31aca912014-03-20 17:14:59 -0700103/* This constant enables extended precision handling.
104 * TODO The flag is off until more testing is done.
105 */
106static const bool k_enable_extended_precision = false;
107
Eric Laurentb23d5282013-05-14 15:27:20 -0700108struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700109 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700110 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
111 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
112 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
113 .format = PCM_FORMAT_S16_LE,
114 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
115 .stop_threshold = INT_MAX,
116 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
117};
118
119struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700120 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700121 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
122 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
123 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
124 .format = PCM_FORMAT_S16_LE,
125 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
126 .stop_threshold = INT_MAX,
127 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
128};
129
Haynes Mathew George03c40102016-01-29 17:57:48 -0800130static int af_period_multiplier = 4;
131struct pcm_config pcm_config_rt = {
132 .channels = DEFAULT_CHANNEL_COUNT,
133 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
134 .period_size = ULL_PERIOD_SIZE, //1 ms
135 .period_count = 512, //=> buffer size is 512ms
136 .format = PCM_FORMAT_S16_LE,
137 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
138 .stop_threshold = INT_MAX,
139 .silence_threshold = 0,
140 .silence_size = 0,
141 .avail_min = ULL_PERIOD_SIZE, //1 ms
142};
143
Eric Laurentb23d5282013-05-14 15:27:20 -0700144struct pcm_config pcm_config_hdmi_multi = {
145 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
146 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
147 .period_size = HDMI_MULTI_PERIOD_SIZE,
148 .period_count = HDMI_MULTI_PERIOD_COUNT,
149 .format = PCM_FORMAT_S16_LE,
150 .start_threshold = 0,
151 .stop_threshold = INT_MAX,
152 .avail_min = 0,
153};
154
Eric Laurent0e46adf2016-12-16 12:49:24 -0800155struct pcm_config pcm_config_mmap_playback = {
156 .channels = DEFAULT_CHANNEL_COUNT,
157 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
158 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800159 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800160 .format = PCM_FORMAT_S16_LE,
161 .start_threshold = MMAP_PERIOD_SIZE*8,
162 .stop_threshold = INT32_MAX,
163 .silence_threshold = 0,
164 .silence_size = 0,
165 .avail_min = MMAP_PERIOD_SIZE, //1 ms
166};
167
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800168struct pcm_config pcm_config_hifi = {
169 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
171 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
172 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
173 .format = PCM_FORMAT_S24_3LE,
174 .start_threshold = 0,
175 .stop_threshold = INT_MAX,
176 .avail_min = 0,
177};
178
Eric Laurentb23d5282013-05-14 15:27:20 -0700179struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700180 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700181 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
182 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700183 .stop_threshold = INT_MAX,
184 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700185};
186
Haynes Mathew George03c40102016-01-29 17:57:48 -0800187struct pcm_config pcm_config_audio_capture_rt = {
188 .channels = DEFAULT_CHANNEL_COUNT,
189 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
190 .period_size = ULL_PERIOD_SIZE,
191 .period_count = 512,
192 .format = PCM_FORMAT_S16_LE,
193 .start_threshold = 0,
194 .stop_threshold = INT_MAX,
195 .silence_threshold = 0,
196 .silence_size = 0,
197 .avail_min = ULL_PERIOD_SIZE, //1 ms
198};
199
Eric Laurent0e46adf2016-12-16 12:49:24 -0800200struct pcm_config pcm_config_mmap_capture = {
201 .channels = DEFAULT_CHANNEL_COUNT,
202 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
203 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800204 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800205 .format = PCM_FORMAT_S16_LE,
206 .start_threshold = 0,
207 .stop_threshold = INT_MAX,
208 .silence_threshold = 0,
209 .silence_size = 0,
210 .avail_min = MMAP_PERIOD_SIZE, //1 ms
211};
212
vivek mehtaa68fea62017-06-08 19:04:02 -0700213struct pcm_config pcm_config_voip = {
214 .channels = 1,
215 .period_count = 2,
216 .format = PCM_FORMAT_S16_LE,
217 .stop_threshold = INT_MAX,
218 .avail_min = 0,
219};
220
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700221#define AFE_PROXY_CHANNEL_COUNT 2
222#define AFE_PROXY_SAMPLING_RATE 48000
223
224#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
225#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
226
227struct pcm_config pcm_config_afe_proxy_playback = {
228 .channels = AFE_PROXY_CHANNEL_COUNT,
229 .rate = AFE_PROXY_SAMPLING_RATE,
230 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
231 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
234 .stop_threshold = INT_MAX,
235 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
236};
237
238#define AFE_PROXY_RECORD_PERIOD_SIZE 768
239#define AFE_PROXY_RECORD_PERIOD_COUNT 4
240
241struct pcm_config pcm_config_afe_proxy_record = {
242 .channels = AFE_PROXY_CHANNEL_COUNT,
243 .rate = AFE_PROXY_SAMPLING_RATE,
244 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
245 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
246 .format = PCM_FORMAT_S16_LE,
247 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
248 .stop_threshold = INT_MAX,
249 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
250};
251
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700252const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700253 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
254 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800255 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700256 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700257 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700258 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800259 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700260
Eric Laurentb23d5282013-05-14 15:27:20 -0700261 [USECASE_AUDIO_RECORD] = "audio-record",
262 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800263 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700264 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700265
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800266 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
267 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700268
Eric Laurentb23d5282013-05-14 15:27:20 -0700269 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700270 [USECASE_VOICE2_CALL] = "voice2-call",
271 [USECASE_VOLTE_CALL] = "volte-call",
272 [USECASE_QCHAT_CALL] = "qchat-call",
273 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800274 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
275 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700276
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700277 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
278 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
279
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700280 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
281 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700282
283 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
284 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
285 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
286
vivek mehtaa68fea62017-06-08 19:04:02 -0700287 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
288 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Eric Laurentb23d5282013-05-14 15:27:20 -0700289};
290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800291
292#define STRING_TO_ENUM(string) { #string, string }
293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800294struct string_to_enum {
295 const char *name;
296 uint32_t value;
297};
298
Haynes Mathew George569b7482017-05-08 14:44:27 -0700299static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800300 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
301 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
302 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700303 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700304 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700305 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
306 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
307 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
308 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
309 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
310 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
311 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
312 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800314};
315
Haynes Mathew George5191a852013-09-11 14:19:36 -0700316static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700317static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700318static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700319static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700320//cache last MBDRC cal step level
321static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700322
Andy Hung9e737de2017-05-22 10:51:22 -0700323// TODO: Consider moving this to a pthread_once() if we have more
324// static initialization required.
325static bool is_userdebug_or_eng_build() {
326 char value[PROPERTY_VALUE_MAX];
327 (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
328 return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
329}
330
Haynes Mathew George03c40102016-01-29 17:57:48 -0800331static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
332 int flags __unused)
333{
334 int dir = 0;
335 switch (uc_id) {
336 case USECASE_AUDIO_RECORD_LOW_LATENCY:
337 dir = 1;
338 case USECASE_AUDIO_PLAYBACK_ULL:
339 break;
340 default:
341 return false;
342 }
343
344 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
345 PCM_PLAYBACK : PCM_CAPTURE);
346 if (adev->adm_is_noirq_avail)
347 return adev->adm_is_noirq_avail(adev->adm_data,
348 adev->snd_card, dev_id, dir);
349 return false;
350}
351
352static void register_out_stream(struct stream_out *out)
353{
354 struct audio_device *adev = out->dev;
355 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
356 return;
357
358 if (!adev->adm_register_output_stream)
359 return;
360
361 adev->adm_register_output_stream(adev->adm_data,
362 out->handle,
363 out->flags);
364
365 if (!adev->adm_set_config)
366 return;
367
368 if (out->realtime) {
369 adev->adm_set_config(adev->adm_data,
370 out->handle,
371 out->pcm, &out->config);
372 }
373}
374
375static void register_in_stream(struct stream_in *in)
376{
377 struct audio_device *adev = in->dev;
378 if (!adev->adm_register_input_stream)
379 return;
380
381 adev->adm_register_input_stream(adev->adm_data,
382 in->capture_handle,
383 in->flags);
384
385 if (!adev->adm_set_config)
386 return;
387
388 if (in->realtime) {
389 adev->adm_set_config(adev->adm_data,
390 in->capture_handle,
391 in->pcm,
392 &in->config);
393 }
394}
395
396static void request_out_focus(struct stream_out *out, long ns)
397{
398 struct audio_device *adev = out->dev;
399
Haynes Mathew George03c40102016-01-29 17:57:48 -0800400 if (adev->adm_request_focus_v2) {
401 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
402 } else if (adev->adm_request_focus) {
403 adev->adm_request_focus(adev->adm_data, out->handle);
404 }
405}
406
407static void request_in_focus(struct stream_in *in, long ns)
408{
409 struct audio_device *adev = in->dev;
410
Haynes Mathew George03c40102016-01-29 17:57:48 -0800411 if (adev->adm_request_focus_v2) {
412 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
413 } else if (adev->adm_request_focus) {
414 adev->adm_request_focus(adev->adm_data, in->capture_handle);
415 }
416}
417
418static void release_out_focus(struct stream_out *out, long ns __unused)
419{
420 struct audio_device *adev = out->dev;
421
422 if (adev->adm_abandon_focus)
423 adev->adm_abandon_focus(adev->adm_data, out->handle);
424}
425
426static void release_in_focus(struct stream_in *in, long ns __unused)
427{
428 struct audio_device *adev = in->dev;
429 if (adev->adm_abandon_focus)
430 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
431}
432
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700433static int parse_snd_card_status(struct str_parms * parms, int * card,
434 card_status_t * status)
435{
436 char value[32]={0};
437 char state[32]={0};
438
439 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
440
441 if (ret < 0)
442 return -1;
443
444 // sscanf should be okay as value is of max length 32.
445 // same as sizeof state.
446 if (sscanf(value, "%d,%s", card, state) < 2)
447 return -1;
448
449 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
450 CARD_STATUS_OFFLINE;
451 return 0;
452}
453
vivek mehta1a9b7c02015-06-25 11:49:38 -0700454__attribute__ ((visibility ("default")))
455bool audio_hw_send_gain_dep_calibration(int level) {
456 bool ret_val = false;
457 ALOGV("%s: enter ... ", __func__);
458
459 pthread_mutex_lock(&adev_init_lock);
460
461 if (adev != NULL && adev->platform != NULL) {
462 pthread_mutex_lock(&adev->lock);
463 ret_val = platform_send_gain_dep_cal(adev->platform, level);
464 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700465
466 // if cal set fails, cache level info
467 // if cal set succeds, reset known last cal set
468 if (!ret_val)
469 last_known_cal_step = level;
470 else if (last_known_cal_step != -1)
471 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700472 } else {
473 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
474 }
475
476 pthread_mutex_unlock(&adev_init_lock);
477
478 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
479 return ret_val;
480}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700481
vivek mehtaa8d7c922016-05-25 14:40:44 -0700482__attribute__ ((visibility ("default")))
483int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
484 int table_size) {
485 int ret_val = 0;
486 ALOGV("%s: enter ... ", __func__);
487
488 pthread_mutex_lock(&adev_init_lock);
489 if (adev == NULL) {
490 ALOGW("%s: adev is NULL .... ", __func__);
491 goto done;
492 }
493
494 pthread_mutex_lock(&adev->lock);
495 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
496 pthread_mutex_unlock(&adev->lock);
497done:
498 pthread_mutex_unlock(&adev_init_lock);
499 ALOGV("%s: exit ... ", __func__);
500 return ret_val;
501}
502
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700503static bool is_supported_format(audio_format_t format)
504{
Eric Laurent8251ac82014-07-23 11:00:25 -0700505 switch (format) {
506 case AUDIO_FORMAT_MP3:
507 case AUDIO_FORMAT_AAC_LC:
508 case AUDIO_FORMAT_AAC_HE_V1:
509 case AUDIO_FORMAT_AAC_HE_V2:
510 return true;
511 default:
512 break;
513 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700514 return false;
515}
516
Haynes Mathew George03c40102016-01-29 17:57:48 -0800517static inline bool is_mmap_usecase(audio_usecase_t uc_id)
518{
519 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
520 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
521}
522
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700523static int get_snd_codec_id(audio_format_t format)
524{
525 int id = 0;
526
Eric Laurent8251ac82014-07-23 11:00:25 -0700527 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700528 case AUDIO_FORMAT_MP3:
529 id = SND_AUDIOCODEC_MP3;
530 break;
531 case AUDIO_FORMAT_AAC:
532 id = SND_AUDIOCODEC_AAC;
533 break;
534 default:
535 ALOGE("%s: Unsupported audio format", __func__);
536 }
537
538 return id;
539}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800540
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800541static int audio_ssr_status(struct audio_device *adev)
542{
543 int ret = 0;
544 struct mixer_ctl *ctl;
545 const char *mixer_ctl_name = "Audio SSR Status";
546
547 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
548 ret = mixer_ctl_get_value(ctl, 0);
549 ALOGD("%s: value: %d", __func__, ret);
550 return ret;
551}
552
vivek mehta4a824772017-06-08 19:05:49 -0700553static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
554{
555 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
556}
557
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800558int enable_audio_route(struct audio_device *adev,
559 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800560{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700561 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800562 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800563
564 if (usecase == NULL)
565 return -EINVAL;
566
567 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
568
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800569 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800571 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800573
Yamit Mehtae3b99562016-09-16 22:44:00 +0530574 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800575 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800576 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500577 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700578 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700579 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800581 ALOGV("%s: exit", __func__);
582 return 0;
583}
584
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800585int disable_audio_route(struct audio_device *adev,
586 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800587{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800589 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800590
591 if (usecase == NULL)
592 return -EINVAL;
593
594 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 if (usecase->type == PCM_CAPTURE)
596 snd_device = usecase->in_snd_device;
597 else
598 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800599 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500600 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700601 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700602 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604 ALOGV("%s: exit", __func__);
605 return 0;
606}
607
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800608int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700609 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800610{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700611 int i, num_devices = 0;
612 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800613 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800614 if (snd_device < SND_DEVICE_MIN ||
615 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800616 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800617 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800618 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700620 platform_send_audio_calibration(adev->platform, snd_device);
621
vivek mehtade4849c2016-03-03 17:23:38 -0800622 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700623 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700624 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800625 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626 }
627
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700628 /* due to the possibility of calibration overwrite between listen
629 and audio, notify sound trigger hal before audio calibration is sent */
630 audio_extn_sound_trigger_update_device_status(snd_device,
631 ST_EVENT_SND_DEVICE_BUSY);
632
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700633 if (audio_extn_spkr_prot_is_enabled())
634 audio_extn_spkr_prot_calib_cancel(adev);
635
zhaoyang yin4211fad2015-06-04 21:13:25 +0800636 audio_extn_dsm_feedback_enable(adev, snd_device, true);
637
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700638 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
639 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
640 audio_extn_spkr_prot_is_enabled()) {
641 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800642 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700643 }
644 if (audio_extn_spkr_prot_start_processing(snd_device)) {
645 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800646 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700647 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700648 } else if (platform_can_split_snd_device(snd_device,
649 &num_devices,
650 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700651 for (i = 0; i < num_devices; i++) {
652 enable_snd_device(adev, new_snd_devices[i]);
653 }
vivek mehtab6506412015-08-07 16:55:17 -0700654 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700655 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800656 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
657 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
658 ALOGE(" %s: Invalid sound device returned", __func__);
659 goto on_error;
660 }
Ed Tam70b5c142016-03-21 19:14:29 -0700661
Eric Laurent2e140aa2016-06-30 17:14:46 -0700662 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800663 audio_route_apply_and_update_path(adev->audio_route, device_name);
664 }
665on_success:
666 adev->snd_dev_ref_cnt[snd_device]++;
667 ret_val = 0;
668on_error:
669 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800670}
671
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800672int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700673 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800674{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700675 int i, num_devices = 0;
676 snd_device_t new_snd_devices[2];
677
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800678 if (snd_device < SND_DEVICE_MIN ||
679 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800680 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800681 return -EINVAL;
682 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
684 ALOGE("%s: device ref cnt is already 0", __func__);
685 return -EINVAL;
686 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800687 audio_extn_tfa_98xx_disable_speaker(snd_device);
688
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700689 adev->snd_dev_ref_cnt[snd_device]--;
690 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800691 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700692 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700693 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700694 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
695 audio_extn_spkr_prot_is_enabled()) {
696 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700697
698 // when speaker device is disabled, reset swap.
699 // will be renabled on usecase start
700 platform_set_swap_channels(adev, false);
701
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700702 } else if (platform_can_split_snd_device(snd_device,
703 &num_devices,
704 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700705 for (i = 0; i < num_devices; i++) {
706 disable_snd_device(adev, new_snd_devices[i]);
707 }
vivek mehtab6506412015-08-07 16:55:17 -0700708 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700709 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800710 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
711 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
712 ALOGE(" %s: Invalid sound device returned", __func__);
713 return -EINVAL;
714 }
715
Eric Laurent2e140aa2016-06-30 17:14:46 -0700716 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800717 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700718 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700719 audio_extn_sound_trigger_update_device_status(snd_device,
720 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 }
vivek mehtab6506412015-08-07 16:55:17 -0700722
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800723 return 0;
724}
725
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700726/*
727 legend:
728 uc - existing usecase
729 new_uc - new usecase
730 d1, d11, d2 - SND_DEVICE enums
731 a1, a2 - corresponding ANDROID device enums
732 B, B1, B2 - backend strings
733
734case 1
735 uc->dev d1 (a1) B1
736 new_uc->dev d1 (a1), d2 (a2) B1, B2
737
738 resolution: disable and enable uc->dev on d1
739
740case 2
741 uc->dev d1 (a1) B1
742 new_uc->dev d11 (a1) B1
743
744 resolution: need to switch uc since d1 and d11 are related
745 (e.g. speaker and voice-speaker)
746 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
747
748case 3
749 uc->dev d1 (a1) B1
750 new_uc->dev d2 (a2) B2
751
752 resolution: no need to switch uc
753
754case 4
755 uc->dev d1 (a1) B
756 new_uc->dev d2 (a2) B
757
758 resolution: disable enable uc-dev on d2 since backends match
759 we cannot enable two streams on two different devices if they
760 share the same backend. e.g. if offload is on speaker device using
761 QUAD_MI2S backend and a low-latency stream is started on voice-handset
762 using the same backend, offload must also be switched to voice-handset.
763
764case 5
765 uc->dev d1 (a1) B
766 new_uc->dev d1 (a1), d2 (a2) B
767
768 resolution: disable enable uc-dev on d2 since backends match
769 we cannot enable two streams on two different devices if they
770 share the same backend.
771
772case 6
773 uc->dev d1 a1 B1
774 new_uc->dev d2 a1 B2
775
776 resolution: no need to switch
777
778case 7
779
780 uc->dev d1 (a1), d2 (a2) B1, B2
781 new_uc->dev d1 B1
782
783 resolution: no need to switch
784
785*/
786static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
787 struct audio_usecase *new_uc,
788 snd_device_t new_snd_device)
789{
790 audio_devices_t a1 = uc->stream.out->devices;
791 audio_devices_t a2 = new_uc->stream.out->devices;
792
793 snd_device_t d1 = uc->out_snd_device;
794 snd_device_t d2 = new_snd_device;
795
796 // Treat as a special case when a1 and a2 are not disjoint
797 if ((a1 != a2) && (a1 & a2)) {
798 snd_device_t d3[2];
799 int num_devices = 0;
800 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
801 &num_devices,
802 d3);
803 if (ret < 0) {
804 if (ret != -ENOSYS) {
805 ALOGW("%s failed to split snd_device %d",
806 __func__,
807 popcount(a1) > 1 ? d1 : d2);
808 }
809 goto end;
810 }
811
812 // NB: case 7 is hypothetical and isn't a practical usecase yet.
813 // But if it does happen, we need to give priority to d2 if
814 // the combo devices active on the existing usecase share a backend.
815 // This is because we cannot have a usecase active on a combo device
816 // and a new usecase requests one device in this combo pair.
817 if (platform_check_backends_match(d3[0], d3[1])) {
818 return d2; // case 5
819 } else {
820 return d1; // case 1
821 }
822 } else {
823 if (platform_check_backends_match(d1, d2)) {
824 return d2; // case 2, 4
825 } else {
826 return d1; // case 6, 3
827 }
828 }
829
830end:
831 return d2; // return whatever was calculated before.
832}
833
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700834static void check_and_route_playback_usecases(struct audio_device *adev,
835 struct audio_usecase *uc_info,
836 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837{
838 struct listnode *node;
839 struct audio_usecase *usecase;
840 bool switch_device[AUDIO_USECASE_MAX];
841 int i, num_uc_to_switch = 0;
842
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700843 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
844 uc_info,
845 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700846
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 /*
848 * This function is to make sure that all the usecases that are active on
849 * the hardware codec backend are always routed to any one device that is
850 * handled by the hardware codec.
851 * For example, if low-latency and deep-buffer usecases are currently active
852 * on speaker and out_set_parameters(headset) is received on low-latency
853 * output, then we have to make sure deep-buffer is also switched to headset,
854 * because of the limitation that both the devices cannot be enabled
855 * at the same time as they share the same backend.
856 */
857 /* Disable all the usecases on the shared backend other than the
858 specified usecase */
859 for (i = 0; i < AUDIO_USECASE_MAX; i++)
860 switch_device[i] = false;
861
862 list_for_each(node, &adev->usecase_list) {
863 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700864 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
865 continue;
866
867 if (force_routing ||
868 (usecase->out_snd_device != snd_device &&
869 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
870 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
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001006static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1007 uint32_t *supported_sample_rates __unused,
1008 uint32_t max_rates __unused)
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) {
1033 // For playback we never report mono because the framework always outputs stereo
1034 channel_count = DEFAULT_CHANNEL_COUNT;
1035 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1036 // above 2 but we want indexed masks here. So we
1037 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1038 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1039 }
1040 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1041 supported_channel_masks[num_masks++] =
1042 audio_channel_mask_for_index_assignment_from_count(channel_count);
1043 }
1044 } else {
1045 // For capture we report all supported channel masks from 1 channel up.
1046 channel_count = MIN_CHANNEL_COUNT;
1047 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1048 // indexed mask
1049 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1050 supported_channel_masks[num_masks++] =
1051 audio_channel_in_mask_from_count(channel_count);
1052 }
1053 }
1054 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1055 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1056 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001057}
1058
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001059static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001060 audio_format_t *supported_formats,
1061 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001062{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001063 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001064 switch (bitwidth) {
1065 case 24:
1066 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001067 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001068 break;
1069 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001071 break;
1072 case 16:
1073 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001074 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001075 break;
1076 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001077 ALOGV("%s: %s supported format %d", __func__,
1078 is_playback ? "P" : "C", bitwidth);
1079 return 1;
1080}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001081
Haynes Mathew George569b7482017-05-08 14:44:27 -07001082static int read_usb_sup_params_and_compare(bool is_playback,
1083 audio_format_t *format,
1084 audio_format_t *supported_formats,
1085 uint32_t max_formats,
1086 audio_channel_mask_t *mask,
1087 audio_channel_mask_t *supported_channel_masks,
1088 uint32_t max_masks,
1089 uint32_t *rate,
1090 uint32_t *supported_sample_rates,
1091 uint32_t max_rates) {
1092 int ret = 0;
1093 int num_formats;
1094 int num_masks;
1095 int num_rates;
1096 int i;
1097
1098 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1099 max_formats);
1100 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1101 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001102
Haynes Mathew George569b7482017-05-08 14:44:27 -07001103 num_rates = read_usb_sup_sample_rates(is_playback,
1104 supported_sample_rates, max_rates);
1105
1106#define LUT(table, len, what, dflt) \
1107 for (i=0; i<len && (table[i] != what); i++); \
1108 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1109
1110 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1111 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1112 LUT(supported_sample_rates, num_rates, *rate, 0);
1113
1114#undef LUT
1115 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001116}
1117
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001118static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1119{
1120 struct audio_usecase *usecase;
1121 struct listnode *node;
1122
1123 list_for_each(node, &adev->usecase_list) {
1124 usecase = node_to_item(node, struct audio_usecase, list);
1125 if (usecase->type == VOICE_CALL) {
1126 ALOGV("%s: usecase id %d", __func__, usecase->id);
1127 return usecase->id;
1128 }
1129 }
1130 return USECASE_INVALID;
1131}
1132
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001133struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1134 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001135{
1136 struct audio_usecase *usecase;
1137 struct listnode *node;
1138
1139 list_for_each(node, &adev->usecase_list) {
1140 usecase = node_to_item(node, struct audio_usecase, list);
1141 if (usecase->id == uc_id)
1142 return usecase;
1143 }
1144 return NULL;
1145}
1146
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001147int select_devices(struct audio_device *adev,
1148 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001149{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001150 snd_device_t out_snd_device = SND_DEVICE_NONE;
1151 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 struct audio_usecase *usecase = NULL;
1153 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001154 struct audio_usecase *hfp_usecase = NULL;
1155 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001156 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001157 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001159 usecase = get_usecase_from_list(adev, uc_id);
1160 if (usecase == NULL) {
1161 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1162 return -EINVAL;
1163 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001165 if ((usecase->type == VOICE_CALL) ||
1166 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001167 out_snd_device = platform_get_output_snd_device(adev->platform,
1168 usecase->stream.out->devices);
1169 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 usecase->devices = usecase->stream.out->devices;
1171 } else {
1172 /*
1173 * If the voice call is active, use the sound devices of voice call usecase
1174 * so that it would not result any device switch. All the usecases will
1175 * be switched to new device when select_devices() is called for voice call
1176 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001177 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001178 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001179 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001180 vc_usecase = get_usecase_from_list(adev,
1181 get_voice_usecase_id_from_list(adev));
1182 if ((vc_usecase != NULL) &&
1183 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1184 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001185 in_snd_device = vc_usecase->in_snd_device;
1186 out_snd_device = vc_usecase->out_snd_device;
1187 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001188 } else if (audio_extn_hfp_is_active(adev)) {
1189 hfp_ucid = audio_extn_hfp_get_usecase();
1190 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1191 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1192 in_snd_device = hfp_usecase->in_snd_device;
1193 out_snd_device = hfp_usecase->out_snd_device;
1194 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195 }
1196 if (usecase->type == PCM_PLAYBACK) {
1197 usecase->devices = usecase->stream.out->devices;
1198 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001199 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001200 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001201 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001202 if (usecase->stream.out == adev->primary_output &&
1203 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001204 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1205 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001206 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001207 select_devices(adev, adev->active_input->usecase);
1208 }
1209 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001210 } else if (usecase->type == PCM_CAPTURE) {
1211 usecase->devices = usecase->stream.in->device;
1212 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001213 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001214 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001215 if (adev->active_input &&
1216 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1217 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001218 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001219 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1220 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1221 } else if (adev->primary_output) {
1222 out_device = adev->primary_output->devices;
1223 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001224 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001225 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001226 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001227 }
1228 }
1229
1230 if (out_snd_device == usecase->out_snd_device &&
1231 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232 return 0;
1233 }
1234
Eric Laurent2bafff12016-03-17 12:17:23 -07001235 if (out_snd_device != SND_DEVICE_NONE &&
1236 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1237 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1238 __func__,
1239 use_case_table[uc_id],
1240 adev->last_logged_snd_device[uc_id][0],
1241 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1242 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1243 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1244 -1,
1245 out_snd_device,
1246 platform_get_snd_device_name(out_snd_device),
1247 platform_get_snd_device_acdb_id(out_snd_device));
1248 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1249 }
1250 if (in_snd_device != SND_DEVICE_NONE &&
1251 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1252 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1253 __func__,
1254 use_case_table[uc_id],
1255 adev->last_logged_snd_device[uc_id][1],
1256 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1257 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1258 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1259 -1,
1260 in_snd_device,
1261 platform_get_snd_device_name(in_snd_device),
1262 platform_get_snd_device_acdb_id(in_snd_device));
1263 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1264 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001265
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001266 /*
1267 * Limitation: While in call, to do a device switch we need to disable
1268 * and enable both RX and TX devices though one of them is same as current
1269 * device.
1270 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001271 if ((usecase->type == VOICE_CALL) &&
1272 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1273 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001274 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001275 /* Disable sidetone only if voice call already exists */
1276 if (voice_is_call_state_active(adev))
1277 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001278 }
1279
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001280 /* Disable current sound devices */
1281 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001282 disable_audio_route(adev, usecase);
1283 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001284 }
1285
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001286 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001287 disable_audio_route(adev, usecase);
1288 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001289 }
1290
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001291 /* Applicable only on the targets that has external modem.
1292 * New device information should be sent to modem before enabling
1293 * the devices to reduce in-call device switch time.
1294 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001295 if ((usecase->type == VOICE_CALL) &&
1296 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1297 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001298 status = platform_switch_voice_call_enable_device_config(adev->platform,
1299 out_snd_device,
1300 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001301 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001302
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001303 /* Enable new sound devices */
1304 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001305 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001306 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001307 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001308 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001309 }
1310
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001311 if (in_snd_device != SND_DEVICE_NONE) {
1312 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001313 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001314 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315
Eric Laurentb23d5282013-05-14 15:27:20 -07001316 if (usecase->type == VOICE_CALL)
1317 status = platform_switch_voice_call_device_post(adev->platform,
1318 out_snd_device,
1319 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001320
sangwoo170731f2013-06-08 15:36:36 +09001321 usecase->in_snd_device = in_snd_device;
1322 usecase->out_snd_device = out_snd_device;
1323
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001324 audio_extn_tfa_98xx_set_mode();
1325
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001326 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001327
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001328 /* Applicable only on the targets that has external modem.
1329 * Enable device command should be sent to modem only after
1330 * enabling voice call mixer controls
1331 */
vivek mehta765eb642015-08-07 19:46:06 -07001332 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001333 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1334 out_snd_device,
1335 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001336 /* Enable sidetone only if voice call already exists */
1337 if (voice_is_call_state_active(adev))
1338 voice_set_sidetone(adev, out_snd_device, true);
1339 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001340
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001341 return status;
1342}
1343
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344static int stop_input_stream(struct stream_in *in)
1345{
1346 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001347 struct audio_usecase *uc_info;
1348 struct audio_device *adev = in->dev;
1349
Eric Laurentc8400632013-02-14 19:04:54 -08001350 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001351
Eric Laurent994a6932013-07-17 11:51:42 -07001352 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001353 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001354 uc_info = get_usecase_from_list(adev, in->usecase);
1355 if (uc_info == NULL) {
1356 ALOGE("%s: Could not find the usecase (%d) in the list",
1357 __func__, in->usecase);
1358 return -EINVAL;
1359 }
1360
vivek mehta781065c2017-04-04 12:55:01 -07001361 /* Close in-call recording streams */
1362 voice_check_and_stop_incall_rec_usecase(adev, in);
1363
Eric Laurent150dbfe2013-02-27 14:31:02 -08001364 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001365 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001366
1367 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001368 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001369
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001370 list_remove(&uc_info->list);
1371 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372
Eric Laurent994a6932013-07-17 11:51:42 -07001373 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374 return ret;
1375}
1376
1377int start_input_stream(struct stream_in *in)
1378{
1379 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001380 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001381 struct audio_usecase *uc_info;
1382 struct audio_device *adev = in->dev;
1383
Eric Laurent994a6932013-07-17 11:51:42 -07001384 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001385
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001386 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1387 return -EIO;
1388
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001389 if (in->card_status == CARD_STATUS_OFFLINE ||
1390 adev->card_status == CARD_STATUS_OFFLINE) {
1391 ALOGW("in->card_status or adev->card_status offline, try again");
1392 ret = -EAGAIN;
1393 goto error_config;
1394 }
1395
vivek mehta781065c2017-04-04 12:55:01 -07001396 /* Check if source matches incall recording usecase criteria */
1397 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1398 if (ret)
1399 goto error_config;
1400 else
1401 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1402
Eric Laurentb23d5282013-05-14 15:27:20 -07001403 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404 if (in->pcm_device_id < 0) {
1405 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1406 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001407 ret = -EINVAL;
1408 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001409 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001410
1411 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001412 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1413 uc_info->id = in->usecase;
1414 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001415 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001416 uc_info->devices = in->device;
1417 uc_info->in_snd_device = SND_DEVICE_NONE;
1418 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001419
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001420 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001421
1422 audio_extn_perf_lock_acquire();
1423
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001424 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425
Eric Laurent0e46adf2016-12-16 12:49:24 -08001426 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001427 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001428 ALOGE("%s: pcm stream not ready", __func__);
1429 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001430 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001431 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001432 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001433 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1434 goto error_open;
1435 }
1436 } else {
1437 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1438 unsigned int pcm_open_retry_count = 0;
1439
1440 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1441 flags |= PCM_MMAP | PCM_NOIRQ;
1442 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1443 } else if (in->realtime) {
1444 flags |= PCM_MMAP | PCM_NOIRQ;
1445 }
1446
1447 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1448 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1449
1450 while (1) {
1451 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1452 flags, &in->config);
1453 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1454 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1455 if (in->pcm != NULL) {
1456 pcm_close(in->pcm);
1457 in->pcm = NULL;
1458 }
1459 if (pcm_open_retry_count-- == 0) {
1460 ret = -EIO;
1461 goto error_open;
1462 }
1463 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1464 continue;
1465 }
1466 break;
1467 }
1468
1469 ALOGV("%s: pcm_prepare", __func__);
1470 ret = pcm_prepare(in->pcm);
1471 if (ret < 0) {
1472 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001473 pcm_close(in->pcm);
1474 in->pcm = NULL;
1475 goto error_open;
1476 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001477 if (in->realtime) {
1478 ret = pcm_start(in->pcm);
1479 if (ret < 0) {
1480 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1481 pcm_close(in->pcm);
1482 in->pcm = NULL;
1483 goto error_open;
1484 }
1485 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001486 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001487 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001488 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001489 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001490
Eric Laurent0e46adf2016-12-16 12:49:24 -08001491 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001492
1493error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001495 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001496
1497error_config:
1498 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001499 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001500 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001501}
1502
Eric Laurenta1478072015-09-21 17:21:52 -07001503void lock_input_stream(struct stream_in *in)
1504{
1505 pthread_mutex_lock(&in->pre_lock);
1506 pthread_mutex_lock(&in->lock);
1507 pthread_mutex_unlock(&in->pre_lock);
1508}
1509
1510void lock_output_stream(struct stream_out *out)
1511{
1512 pthread_mutex_lock(&out->pre_lock);
1513 pthread_mutex_lock(&out->lock);
1514 pthread_mutex_unlock(&out->pre_lock);
1515}
1516
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001517/* must be called with out->lock locked */
1518static int send_offload_cmd_l(struct stream_out* out, int command)
1519{
1520 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1521
1522 ALOGVV("%s %d", __func__, command);
1523
1524 cmd->cmd = command;
1525 list_add_tail(&out->offload_cmd_list, &cmd->node);
1526 pthread_cond_signal(&out->offload_cond);
1527 return 0;
1528}
1529
1530/* must be called iwth out->lock locked */
1531static void stop_compressed_output_l(struct stream_out *out)
1532{
1533 out->offload_state = OFFLOAD_STATE_IDLE;
1534 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001535 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001536 if (out->compr != NULL) {
1537 compress_stop(out->compr);
1538 while (out->offload_thread_blocked) {
1539 pthread_cond_wait(&out->cond, &out->lock);
1540 }
1541 }
1542}
1543
1544static void *offload_thread_loop(void *context)
1545{
1546 struct stream_out *out = (struct stream_out *) context;
1547 struct listnode *item;
1548
1549 out->offload_state = OFFLOAD_STATE_IDLE;
1550 out->playback_started = 0;
1551
1552 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1553 set_sched_policy(0, SP_FOREGROUND);
1554 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1555
1556 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001557 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001558 for (;;) {
1559 struct offload_cmd *cmd = NULL;
1560 stream_callback_event_t event;
1561 bool send_callback = false;
1562
1563 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1564 __func__, list_empty(&out->offload_cmd_list),
1565 out->offload_state);
1566 if (list_empty(&out->offload_cmd_list)) {
1567 ALOGV("%s SLEEPING", __func__);
1568 pthread_cond_wait(&out->offload_cond, &out->lock);
1569 ALOGV("%s RUNNING", __func__);
1570 continue;
1571 }
1572
1573 item = list_head(&out->offload_cmd_list);
1574 cmd = node_to_item(item, struct offload_cmd, node);
1575 list_remove(item);
1576
1577 ALOGVV("%s STATE %d CMD %d out->compr %p",
1578 __func__, out->offload_state, cmd->cmd, out->compr);
1579
1580 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1581 free(cmd);
1582 break;
1583 }
1584
1585 if (out->compr == NULL) {
1586 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001587 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001588 pthread_cond_signal(&out->cond);
1589 continue;
1590 }
1591 out->offload_thread_blocked = true;
1592 pthread_mutex_unlock(&out->lock);
1593 send_callback = false;
1594 switch(cmd->cmd) {
1595 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1596 compress_wait(out->compr, -1);
1597 send_callback = true;
1598 event = STREAM_CBK_EVENT_WRITE_READY;
1599 break;
1600 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001601 compress_next_track(out->compr);
1602 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001603 send_callback = true;
1604 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001605 /* Resend the metadata for next iteration */
1606 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001607 break;
1608 case OFFLOAD_CMD_DRAIN:
1609 compress_drain(out->compr);
1610 send_callback = true;
1611 event = STREAM_CBK_EVENT_DRAIN_READY;
1612 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001613 case OFFLOAD_CMD_ERROR:
1614 send_callback = true;
1615 event = STREAM_CBK_EVENT_ERROR;
1616 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001617 default:
1618 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1619 break;
1620 }
Eric Laurenta1478072015-09-21 17:21:52 -07001621 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001622 out->offload_thread_blocked = false;
1623 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001624 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001625 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001626 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001627 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001628 free(cmd);
1629 }
1630
1631 pthread_cond_signal(&out->cond);
1632 while (!list_empty(&out->offload_cmd_list)) {
1633 item = list_head(&out->offload_cmd_list);
1634 list_remove(item);
1635 free(node_to_item(item, struct offload_cmd, node));
1636 }
1637 pthread_mutex_unlock(&out->lock);
1638
1639 return NULL;
1640}
1641
1642static int create_offload_callback_thread(struct stream_out *out)
1643{
1644 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1645 list_init(&out->offload_cmd_list);
1646 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1647 offload_thread_loop, out);
1648 return 0;
1649}
1650
1651static int destroy_offload_callback_thread(struct stream_out *out)
1652{
Eric Laurenta1478072015-09-21 17:21:52 -07001653 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001654 stop_compressed_output_l(out);
1655 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1656
1657 pthread_mutex_unlock(&out->lock);
1658 pthread_join(out->offload_thread, (void **) NULL);
1659 pthread_cond_destroy(&out->offload_cond);
1660
1661 return 0;
1662}
1663
Eric Laurent07eeafd2013-10-06 12:52:49 -07001664static bool allow_hdmi_channel_config(struct audio_device *adev)
1665{
1666 struct listnode *node;
1667 struct audio_usecase *usecase;
1668 bool ret = true;
1669
1670 list_for_each(node, &adev->usecase_list) {
1671 usecase = node_to_item(node, struct audio_usecase, list);
1672 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1673 /*
1674 * If voice call is already existing, do not proceed further to avoid
1675 * disabling/enabling both RX and TX devices, CSD calls, etc.
1676 * Once the voice call done, the HDMI channels can be configured to
1677 * max channels of remaining use cases.
1678 */
1679 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001680 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001681 __func__);
1682 ret = false;
1683 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001684 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1685 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001686 "no change in HDMI channels", __func__);
1687 ret = false;
1688 break;
1689 }
1690 }
1691 }
1692 return ret;
1693}
1694
1695static int check_and_set_hdmi_channels(struct audio_device *adev,
1696 unsigned int channels)
1697{
1698 struct listnode *node;
1699 struct audio_usecase *usecase;
1700
1701 /* Check if change in HDMI channel config is allowed */
1702 if (!allow_hdmi_channel_config(adev))
1703 return 0;
1704
1705 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001706 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001707 return 0;
1708 }
1709
1710 platform_set_hdmi_channels(adev->platform, channels);
1711 adev->cur_hdmi_channels = channels;
1712
1713 /*
1714 * Deroute all the playback streams routed to HDMI so that
1715 * the back end is deactivated. Note that backend will not
1716 * be deactivated if any one stream is connected to it.
1717 */
1718 list_for_each(node, &adev->usecase_list) {
1719 usecase = node_to_item(node, struct audio_usecase, list);
1720 if (usecase->type == PCM_PLAYBACK &&
1721 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001722 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001723 }
1724 }
1725
1726 /*
1727 * Enable all the streams disabled above. Now the HDMI backend
1728 * will be activated with new channel configuration
1729 */
1730 list_for_each(node, &adev->usecase_list) {
1731 usecase = node_to_item(node, struct audio_usecase, list);
1732 if (usecase->type == PCM_PLAYBACK &&
1733 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001734 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001735 }
1736 }
1737
1738 return 0;
1739}
1740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741static int stop_output_stream(struct stream_out *out)
1742{
1743 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744 struct audio_usecase *uc_info;
1745 struct audio_device *adev = out->dev;
1746
Eric Laurent994a6932013-07-17 11:51:42 -07001747 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001748 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749 uc_info = get_usecase_from_list(adev, out->usecase);
1750 if (uc_info == NULL) {
1751 ALOGE("%s: Could not find the usecase (%d) in the list",
1752 __func__, out->usecase);
1753 return -EINVAL;
1754 }
1755
Haynes Mathew George41f86652014-06-17 14:22:15 -07001756 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1757 if (adev->visualizer_stop_output != NULL)
1758 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1759 if (adev->offload_effects_stop_output != NULL)
1760 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1761 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001762
Eric Laurent150dbfe2013-02-27 14:31:02 -08001763 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001764 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001765
1766 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001767 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001769 list_remove(&uc_info->list);
1770 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771
Eric Laurent0499d4f2014-08-25 22:39:29 -05001772 audio_extn_extspk_update(adev->extspk);
1773
Eric Laurent07eeafd2013-10-06 12:52:49 -07001774 /* Must be called after removing the usecase from list */
1775 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1776 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1777
Eric Laurent994a6932013-07-17 11:51:42 -07001778 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779 return ret;
1780}
1781
1782int start_output_stream(struct stream_out *out)
1783{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 struct audio_usecase *uc_info;
1786 struct audio_device *adev = out->dev;
1787
Eric Laurent994a6932013-07-17 11:51:42 -07001788 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001789 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001790
1791 if (out->card_status == CARD_STATUS_OFFLINE ||
1792 adev->card_status == CARD_STATUS_OFFLINE) {
1793 ALOGW("out->card_status or adev->card_status offline, try again");
1794 ret = -EAGAIN;
1795 goto error_config;
1796 }
1797
Eric Laurentb23d5282013-05-14 15:27:20 -07001798 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799 if (out->pcm_device_id < 0) {
1800 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1801 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001802 ret = -EINVAL;
1803 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804 }
1805
1806 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1807 uc_info->id = out->usecase;
1808 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001809 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001810 uc_info->devices = out->devices;
1811 uc_info->in_snd_device = SND_DEVICE_NONE;
1812 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001813
Eric Laurent07eeafd2013-10-06 12:52:49 -07001814 /* This must be called before adding this usecase to the list */
1815 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1816 check_and_set_hdmi_channels(adev, out->config.channels);
1817
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001818 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001820 audio_extn_perf_lock_acquire();
1821
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 select_devices(adev, out->usecase);
1823
Eric Laurent0499d4f2014-08-25 22:39:29 -05001824 audio_extn_extspk_update(adev->extspk);
1825
Andy Hung31aca912014-03-20 17:14:59 -07001826 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001827 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001828 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1829 out->pcm = NULL;
1830 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1831 COMPRESS_IN, &out->compr_config);
1832 if (out->compr && !is_compress_ready(out->compr)) {
1833 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1834 compress_close(out->compr);
1835 out->compr = NULL;
1836 ret = -EIO;
1837 goto error_open;
1838 }
1839 if (out->offload_callback)
1840 compress_nonblock(out->compr, out->non_blocking);
1841
1842 if (adev->visualizer_start_output != NULL)
1843 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1844 if (adev->offload_effects_start_output != NULL)
1845 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1846 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001847 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001848 ALOGE("%s: pcm stream not ready", __func__);
1849 goto error_open;
1850 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001851 ret = pcm_start(out->pcm);
1852 if (ret < 0) {
1853 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1854 goto error_open;
1855 }
1856 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001857 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001858 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001859
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001860 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1861 flags |= PCM_MMAP | PCM_NOIRQ;
1862 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001863 } else if (out->realtime) {
1864 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001865 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001866
1867 while (1) {
1868 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1869 flags, &out->config);
1870 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1871 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1872 if (out->pcm != NULL) {
1873 pcm_close(out->pcm);
1874 out->pcm = NULL;
1875 }
1876 if (pcm_open_retry_count-- == 0) {
1877 ret = -EIO;
1878 goto error_open;
1879 }
1880 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1881 continue;
1882 }
1883 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001884 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001885 ALOGV("%s: pcm_prepare", __func__);
1886 if (pcm_is_ready(out->pcm)) {
1887 ret = pcm_prepare(out->pcm);
1888 if (ret < 0) {
1889 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1890 pcm_close(out->pcm);
1891 out->pcm = NULL;
1892 goto error_open;
1893 }
1894 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001895 if (out->realtime) {
1896 ret = pcm_start(out->pcm);
1897 if (ret < 0) {
1898 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1899 pcm_close(out->pcm);
1900 out->pcm = NULL;
1901 goto error_open;
1902 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001903 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001904 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001905 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001906 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001907 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001908 audio_extn_utils_send_app_type_gain(out->dev,
1909 out->app_type_cfg.app_type,
1910 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001911
1912 // consider a scenario where on pause lower layers are tear down.
1913 // so on resume, swap mixer control need to be sent only when
1914 // backend is active, hence rather than sending from enable device
1915 // sending it from start of streamtream
1916
1917 platform_set_swap_channels(adev, true);
1918
Eric Laurent994a6932013-07-17 11:51:42 -07001919 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001920 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001921error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001922 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001924error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001925 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926}
1927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928static int check_input_parameters(uint32_t sample_rate,
1929 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001930 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001932 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1933 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001934 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1935 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001936 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1937 return -EINVAL;
1938 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939
Eric Laurent74b55762017-07-09 17:04:53 -07001940 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1941 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001942 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001943 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001944 return -EINVAL;
1945 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946
1947 switch (sample_rate) {
1948 case 8000:
1949 case 11025:
1950 case 12000:
1951 case 16000:
1952 case 22050:
1953 case 24000:
1954 case 32000:
1955 case 44100:
1956 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001957 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958 break;
1959 default:
vivek mehtadae44712015-07-27 14:13:18 -07001960 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 return -EINVAL;
1962 }
1963
1964 return 0;
1965}
1966
vivek mehtaa68fea62017-06-08 19:04:02 -07001967static size_t get_stream_buffer_size(size_t duration_ms,
1968 uint32_t sample_rate,
1969 audio_format_t format,
1970 int channel_count,
1971 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972{
1973 size_t size = 0;
1974
vivek mehtaa68fea62017-06-08 19:04:02 -07001975 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001976 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001977 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001978
1979 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980
Glenn Kasten4f993392014-05-14 07:30:48 -07001981 /* make sure the size is multiple of 32 bytes
1982 * At 48 kHz mono 16-bit PCM:
1983 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1984 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1985 */
1986 size += 0x1f;
1987 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001988
1989 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990}
1991
1992static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1993{
1994 struct stream_out *out = (struct stream_out *)stream;
1995
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001996 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997}
1998
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001999static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000{
2001 return -ENOSYS;
2002}
2003
2004static size_t out_get_buffer_size(const struct audio_stream *stream)
2005{
2006 struct stream_out *out = (struct stream_out *)stream;
2007
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002008 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2009 return out->compr_config.fragment_size;
2010 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002011 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002012 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002013}
2014
2015static uint32_t out_get_channels(const struct audio_stream *stream)
2016{
2017 struct stream_out *out = (struct stream_out *)stream;
2018
2019 return out->channel_mask;
2020}
2021
2022static audio_format_t out_get_format(const struct audio_stream *stream)
2023{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002024 struct stream_out *out = (struct stream_out *)stream;
2025
2026 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027}
2028
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002029static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030{
2031 return -ENOSYS;
2032}
2033
2034static int out_standby(struct audio_stream *stream)
2035{
2036 struct stream_out *out = (struct stream_out *)stream;
2037 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002038 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002039
Eric Laurent994a6932013-07-17 11:51:42 -07002040 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002041 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042
Eric Laurenta1478072015-09-21 17:21:52 -07002043 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002045 if (adev->adm_deregister_stream)
2046 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002047 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002049 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2050 if (out->pcm) {
2051 pcm_close(out->pcm);
2052 out->pcm = NULL;
2053 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002054 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002055 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002056 out->playback_started = false;
2057 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 } else {
2059 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002060 out->gapless_mdata.encoder_delay = 0;
2061 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002062 if (out->compr != NULL) {
2063 compress_close(out->compr);
2064 out->compr = NULL;
2065 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002066 }
Phil Burkbc991042017-02-24 08:06:44 -08002067 if (do_stop) {
2068 stop_output_stream(out);
2069 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002070 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071 }
2072 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002073 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074 return 0;
2075}
2076
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002077static int out_on_error(struct audio_stream *stream)
2078{
2079 struct stream_out *out = (struct stream_out *)stream;
2080 struct audio_device *adev = out->dev;
2081 bool do_standby = false;
2082
2083 lock_output_stream(out);
2084 if (!out->standby) {
2085 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2086 stop_compressed_output_l(out);
2087 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2088 } else
2089 do_standby = true;
2090 }
2091 pthread_mutex_unlock(&out->lock);
2092
2093 if (do_standby)
2094 return out_standby(&out->stream.common);
2095
2096 return 0;
2097}
2098
Andy Hung7401c7c2016-09-21 12:41:21 -07002099static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100{
Andy Hung7401c7c2016-09-21 12:41:21 -07002101 struct stream_out *out = (struct stream_out *)stream;
2102
2103 // We try to get the lock for consistency,
2104 // but it isn't necessary for these variables.
2105 // If we're not in standby, we may be blocked on a write.
2106 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2107 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2108 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2109
2110 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002111 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002112 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002113
2114 // dump error info
2115 (void)error_log_dump(
2116 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002117 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002118 (void)power_log_dump(
2119 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 return 0;
2121}
2122
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002123static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2124{
2125 int ret = 0;
2126 char value[32];
2127 struct compr_gapless_mdata tmp_mdata;
2128
2129 if (!out || !parms) {
2130 return -EINVAL;
2131 }
2132
2133 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2134 if (ret >= 0) {
2135 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2136 } else {
2137 return -EINVAL;
2138 }
2139
2140 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2141 if (ret >= 0) {
2142 tmp_mdata.encoder_padding = atoi(value);
2143 } else {
2144 return -EINVAL;
2145 }
2146
2147 out->gapless_mdata = tmp_mdata;
2148 out->send_new_metadata = 1;
2149 ALOGV("%s new encoder delay %u and padding %u", __func__,
2150 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2151
2152 return 0;
2153}
2154
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002155static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2156{
2157 return out == adev->primary_output || out == adev->voice_tx_output;
2158}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002159
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2161{
2162 struct stream_out *out = (struct stream_out *)stream;
2163 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002164 struct audio_usecase *usecase;
2165 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 struct str_parms *parms;
2167 char value[32];
2168 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002169 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002170 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171
Eric Laurent2e140aa2016-06-30 17:14:46 -07002172 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002173 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 parms = str_parms_create_str(kvpairs);
2175 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2176 if (ret >= 0) {
2177 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002178 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002179 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002181 /*
2182 * When HDMI cable is unplugged the music playback is paused and
2183 * the policy manager sends routing=0. But the audioflinger
2184 * continues to write data until standby time (3sec).
2185 * As the HDMI core is turned off, the write gets blocked.
2186 * Avoid this by routing audio to speaker until standby.
2187 */
2188 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2189 val == AUDIO_DEVICE_NONE) {
2190 val = AUDIO_DEVICE_OUT_SPEAKER;
2191 }
2192
2193 /*
2194 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002195 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002196 * the select_devices(). But how do we undo this?
2197 *
2198 * For example, music playback is active on headset (deep-buffer usecase)
2199 * and if we go to ringtones and select a ringtone, low-latency usecase
2200 * will be started on headset+speaker. As we can't enable headset+speaker
2201 * and headset devices at the same time, select_devices() switches the music
2202 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2203 * So when the ringtone playback is completed, how do we undo the same?
2204 *
2205 * We are relying on the out_set_parameters() call on deep-buffer output,
2206 * once the ringtone playback is ended.
2207 * NOTE: We should not check if the current devices are same as new devices.
2208 * Because select_devices() must be called to switch back the music
2209 * playback to headset.
2210 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002211 audio_devices_t new_dev = val;
2212 if (new_dev != AUDIO_DEVICE_NONE) {
2213 bool same_dev = out->devices == new_dev;
2214 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002215
Eric Laurenta7657192014-10-09 21:09:33 -07002216 if (output_drives_call(adev, out)) {
2217 if (!voice_is_in_call(adev)) {
2218 if (adev->mode == AUDIO_MODE_IN_CALL) {
2219 adev->current_call_output = out;
2220 ret = voice_start_call(adev);
2221 }
2222 } else {
2223 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002224 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002225 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002226 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002227
2228 if (!out->standby) {
2229 if (!same_dev) {
2230 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002231 // inform adm before actual routing to prevent glitches.
2232 if (adev->adm_on_routing_change) {
2233 adev->adm_on_routing_change(adev->adm_data,
2234 out->handle);
2235 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002236 }
2237 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002238 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002239
2240 // on device switch force swap, lower functions will make sure
2241 // to check if swap is allowed or not.
2242
2243 if (!same_dev)
2244 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002245 }
2246
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002247 }
2248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002249 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002250 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002251
2252 /*handles device and call state changes*/
2253 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002255
2256 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2257 parse_compress_metadata(out, parms);
2258 }
2259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002261 ALOGV("%s: exit: code(%d)", __func__, status);
2262 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263}
2264
Haynes Mathew George569b7482017-05-08 14:44:27 -07002265static bool stream_get_parameter_channels(struct str_parms *query,
2266 struct str_parms *reply,
2267 audio_channel_mask_t *supported_channel_masks) {
2268 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002269 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002271 size_t i, j;
2272
2273 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2274 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002275 value[0] = '\0';
2276 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002277 while (supported_channel_masks[i] != 0) {
2278 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2279 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280 if (!first) {
2281 strcat(value, "|");
2282 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002283 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284 first = false;
2285 break;
2286 }
2287 }
2288 i++;
2289 }
2290 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002291 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002292 return ret >= 0;
2293}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002294
Haynes Mathew George569b7482017-05-08 14:44:27 -07002295static bool stream_get_parameter_formats(struct str_parms *query,
2296 struct str_parms *reply,
2297 audio_format_t *supported_formats) {
2298 int ret = -1;
2299 char value[256];
2300 int i;
2301
2302 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2303 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002304 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002305 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002306 case AUDIO_FORMAT_PCM_16_BIT:
2307 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2308 break;
2309 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2310 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2311 break;
2312 case AUDIO_FORMAT_PCM_32_BIT:
2313 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2314 break;
2315 default:
2316 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002317 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002318 break;
2319 }
2320 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002321 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002322 return ret >= 0;
2323}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002324
Haynes Mathew George569b7482017-05-08 14:44:27 -07002325static bool stream_get_parameter_rates(struct str_parms *query,
2326 struct str_parms *reply,
2327 uint32_t *supported_sample_rates) {
2328
2329 int i;
2330 char value[256];
2331 int ret = -1;
2332 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2333 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002334 value[0] = '\0';
2335 i=0;
2336 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002337 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002338 int avail = sizeof(value) - cursor;
2339 ret = snprintf(value + cursor, avail, "%s%d",
2340 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002341 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002342 if (ret < 0 || ret >= avail) {
2343 // if cursor is at the last element of the array
2344 // overwrite with \0 is duplicate work as
2345 // snprintf already put a \0 in place.
2346 // else
2347 // we had space to write the '|' at value[cursor]
2348 // (which will be overwritten) or no space to fill
2349 // the first element (=> cursor == 0)
2350 value[cursor] = '\0';
2351 break;
2352 }
2353 cursor += ret;
2354 ++i;
2355 }
2356 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2357 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002358 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002359 return ret >= 0;
2360}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002361
Haynes Mathew George569b7482017-05-08 14:44:27 -07002362static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2363{
2364 struct stream_out *out = (struct stream_out *)stream;
2365 struct str_parms *query = str_parms_create_str(keys);
2366 char *str;
2367 struct str_parms *reply = str_parms_create();
2368 bool replied = false;
2369 ALOGV("%s: enter: keys - %s", __func__, keys);
2370
2371 replied |= stream_get_parameter_channels(query, reply,
2372 &out->supported_channel_masks[0]);
2373 replied |= stream_get_parameter_formats(query, reply,
2374 &out->supported_formats[0]);
2375 replied |= stream_get_parameter_rates(query, reply,
2376 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002377 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002378 str = str_parms_to_str(reply);
2379 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002380 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381 }
2382 str_parms_destroy(query);
2383 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002384 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385 return str;
2386}
2387
2388static uint32_t out_get_latency(const struct audio_stream_out *stream)
2389{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002390 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002391 struct stream_out *out = (struct stream_out *)stream;
2392
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2394 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002395 else if ((out->realtime) ||
2396 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002397 // since the buffer won't be filled up faster than realtime,
2398 // return a smaller number
2399 period_ms = (out->af_period_multiplier * out->config.period_size *
2400 1000) / (out->config.rate);
2401 hw_delay = platform_render_latency(out->usecase)/1000;
2402 return period_ms + hw_delay;
2403 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404
2405 return (out->config.period_count * out->config.period_size * 1000) /
2406 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002407}
2408
2409static int out_set_volume(struct audio_stream_out *stream, float left,
2410 float right)
2411{
Eric Laurenta9024de2013-04-04 09:19:12 -07002412 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 int volume[2];
2414
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002415 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002416 /* only take left channel into account: the API is for stereo anyway */
2417 out->muted = (left == 0.0f);
2418 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002419 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2420 const char *mixer_ctl_name = "Compress Playback Volume";
2421 struct audio_device *adev = out->dev;
2422 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002423 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2424 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002425 /* try with the control based on device id */
2426 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2427 PCM_PLAYBACK);
2428 char ctl_name[128] = {0};
2429 snprintf(ctl_name, sizeof(ctl_name),
2430 "Compress Playback %d Volume", pcm_device_id);
2431 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2432 if (!ctl) {
2433 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2434 return -EINVAL;
2435 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002436 }
2437 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2438 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2439 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2440 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002441 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002442 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2443 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2444 if (!out->standby) {
2445 // if in standby, cached volume will be sent after stream is opened
2446 audio_extn_utils_send_app_type_gain(out->dev,
2447 out->app_type_cfg.app_type,
2448 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002449 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002450 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002451 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002452
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453 return -ENOSYS;
2454}
2455
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002456// note: this call is safe only if the stream_cb is
2457// removed first in close_output_stream (as is done now).
2458static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2459{
2460 if (!stream || !parms)
2461 return;
2462
2463 struct stream_out *out = (struct stream_out *)stream;
2464 struct audio_device *adev = out->dev;
2465
2466 card_status_t status;
2467 int card;
2468 if (parse_snd_card_status(parms, &card, &status) < 0)
2469 return;
2470
2471 pthread_mutex_lock(&adev->lock);
2472 bool valid_cb = (card == adev->snd_card);
2473 pthread_mutex_unlock(&adev->lock);
2474
2475 if (!valid_cb)
2476 return;
2477
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002478 lock_output_stream(out);
2479 if (out->card_status != status)
2480 out->card_status = status;
2481 pthread_mutex_unlock(&out->lock);
2482
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002483 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2484 use_case_table[out->usecase],
2485 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2486
2487 if (status == CARD_STATUS_OFFLINE)
2488 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002489
2490 return;
2491}
2492
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002493#ifdef NO_AUDIO_OUT
2494static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002495 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002496{
2497 struct stream_out *out = (struct stream_out *)stream;
2498
2499 /* No Output device supported other than BT for playback.
2500 * Sleep for the amount of buffer duration
2501 */
Eric Laurenta1478072015-09-21 17:21:52 -07002502 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002503 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2504 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002505 out_get_sample_rate(&out->stream.common));
2506 pthread_mutex_unlock(&out->lock);
2507 return bytes;
2508}
2509#endif
2510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2512 size_t bytes)
2513{
2514 struct stream_out *out = (struct stream_out *)stream;
2515 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002516 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002517 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518
Eric Laurenta1478072015-09-21 17:21:52 -07002519 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002520 // this is always nonzero
Andy Hung928efbe2017-06-12 14:05:22 -07002521 const size_t frame_size = audio_stream_out_frame_size(stream);
2522 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002523
Eric Laurent0e46adf2016-12-16 12:49:24 -08002524 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2525 error_code = ERROR_CODE_WRITE;
2526 goto exit;
2527 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002529 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002530 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002531 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002532 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002535 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002536 goto exit;
2537 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002538
2539 if (last_known_cal_step != -1) {
2540 ALOGD("%s: retry previous failed cal level set", __func__);
2541 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2542 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002545 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002546 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002547 if (out->send_new_metadata) {
2548 ALOGVV("send new gapless metadata");
2549 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2550 out->send_new_metadata = 0;
2551 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002552 unsigned int avail;
2553 struct timespec tstamp;
2554 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2555 /* Do not limit write size if the available frames count is unknown */
2556 if (ret != 0) {
2557 avail = bytes;
2558 }
2559 if (avail == 0) {
2560 ret = 0;
2561 } else {
2562 if (avail > bytes) {
2563 avail = bytes;
2564 }
2565 ret = compress_write(out->compr, buffer, avail);
2566 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2567 __func__, avail, ret);
2568 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002569
Eric Laurent6e895242013-09-05 16:10:57 -07002570 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002571 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2572 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002573 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002574 compress_start(out->compr);
2575 out->playback_started = 1;
2576 out->offload_state = OFFLOAD_STATE_PLAYING;
2577 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002578 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002579 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002580 } else {
2581 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002582 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002583 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002584 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002585 return ret;
2586 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002587 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002588 if (out->pcm) {
2589 if (out->muted)
2590 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002591
Eric Laurent0e46adf2016-12-16 12:49:24 -08002592 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002593
Haynes Mathew George03c40102016-01-29 17:57:48 -08002594 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2595 out->config.rate;
2596 request_out_focus(out, ns);
2597
2598 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2599 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002600 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002601 else
2602 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002603
Haynes Mathew George03c40102016-01-29 17:57:48 -08002604 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002605 } else {
2606 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002607 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 }
2609
2610exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002611 // For PCM we always consume the buffer and return #bytes regardless of ret.
2612 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung928efbe2017-06-12 14:05:22 -07002613 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002614 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002615 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002616
2617 // only get time if needed for logging, as it is a system call on 32 bit devices.
2618 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2619 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2620 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002621
Andy Hung7401c7c2016-09-21 12:41:21 -07002622 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002623 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002624 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2625 ALOGE_IF(out->pcm != NULL,
2626 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung928efbe2017-06-12 14:05:22 -07002627 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002628 // usleep not guaranteed for values over 1 second but we don't limit here.
2629 }
2630 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632 pthread_mutex_unlock(&out->lock);
2633
2634 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002635 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002636 if (sleeptime_us != 0)
2637 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002638 } else {
2639 // only log if the data is properly written (out->power_log may be null)
Andy Hung928efbe2017-06-12 14:05:22 -07002640 power_log_log(out->power_log, buffer, frames, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 }
2642 return bytes;
2643}
2644
2645static int out_get_render_position(const struct audio_stream_out *stream,
2646 uint32_t *dsp_frames)
2647{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002648 struct stream_out *out = (struct stream_out *)stream;
2649 *dsp_frames = 0;
2650 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002651 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002652 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002653 unsigned long frames = 0;
2654 // TODO: check return value
2655 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2656 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002657 ALOGVV("%s rendered frames %d sample_rate %d",
2658 __func__, *dsp_frames, out->sample_rate);
2659 }
2660 pthread_mutex_unlock(&out->lock);
2661 return 0;
2662 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002663 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664}
2665
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002666static int out_add_audio_effect(const struct audio_stream *stream __unused,
2667 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668{
2669 return 0;
2670}
2671
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002672static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2673 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002674{
2675 return 0;
2676}
2677
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002678static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2679 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002681 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682}
2683
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002684static int out_get_presentation_position(const struct audio_stream_out *stream,
2685 uint64_t *frames, struct timespec *timestamp)
2686{
2687 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002688 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002689 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002690
Eric Laurenta1478072015-09-21 17:21:52 -07002691 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002692
Eric Laurent949a0892013-09-20 09:20:13 -07002693 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2694 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002695 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002696 compress_get_tstamp(out->compr, &dsp_frames,
2697 &out->sample_rate);
2698 ALOGVV("%s rendered frames %ld sample_rate %d",
2699 __func__, dsp_frames, out->sample_rate);
2700 *frames = dsp_frames;
2701 ret = 0;
2702 /* this is the best we can do */
2703 clock_gettime(CLOCK_MONOTONIC, timestamp);
2704 }
2705 } else {
2706 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002707 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002708 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2709 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002710 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002711 // This adjustment accounts for buffering after app processor.
2712 // It is based on estimated DSP latency per use case, rather than exact.
2713 signed_frames -=
2714 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2715
Eric Laurent949a0892013-09-20 09:20:13 -07002716 // It would be unusual for this value to be negative, but check just in case ...
2717 if (signed_frames >= 0) {
2718 *frames = signed_frames;
2719 ret = 0;
2720 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002721 }
2722 }
2723 }
2724
2725 pthread_mutex_unlock(&out->lock);
2726
2727 return ret;
2728}
2729
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002730static int out_set_callback(struct audio_stream_out *stream,
2731 stream_callback_t callback, void *cookie)
2732{
2733 struct stream_out *out = (struct stream_out *)stream;
2734
2735 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002736 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002737 out->offload_callback = callback;
2738 out->offload_cookie = cookie;
2739 pthread_mutex_unlock(&out->lock);
2740 return 0;
2741}
2742
2743static int out_pause(struct audio_stream_out* stream)
2744{
2745 struct stream_out *out = (struct stream_out *)stream;
2746 int status = -ENOSYS;
2747 ALOGV("%s", __func__);
2748 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002749 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002750 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2751 status = compress_pause(out->compr);
2752 out->offload_state = OFFLOAD_STATE_PAUSED;
2753 }
2754 pthread_mutex_unlock(&out->lock);
2755 }
2756 return status;
2757}
2758
2759static int out_resume(struct audio_stream_out* stream)
2760{
2761 struct stream_out *out = (struct stream_out *)stream;
2762 int status = -ENOSYS;
2763 ALOGV("%s", __func__);
2764 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2765 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002766 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002767 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2768 status = compress_resume(out->compr);
2769 out->offload_state = OFFLOAD_STATE_PLAYING;
2770 }
2771 pthread_mutex_unlock(&out->lock);
2772 }
2773 return status;
2774}
2775
2776static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2777{
2778 struct stream_out *out = (struct stream_out *)stream;
2779 int status = -ENOSYS;
2780 ALOGV("%s", __func__);
2781 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002782 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002783 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2784 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2785 else
2786 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2787 pthread_mutex_unlock(&out->lock);
2788 }
2789 return status;
2790}
2791
2792static int out_flush(struct audio_stream_out* stream)
2793{
2794 struct stream_out *out = (struct stream_out *)stream;
2795 ALOGV("%s", __func__);
2796 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002797 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002798 stop_compressed_output_l(out);
2799 pthread_mutex_unlock(&out->lock);
2800 return 0;
2801 }
2802 return -ENOSYS;
2803}
2804
Eric Laurent0e46adf2016-12-16 12:49:24 -08002805static int out_stop(const struct audio_stream_out* stream)
2806{
2807 struct stream_out *out = (struct stream_out *)stream;
2808 struct audio_device *adev = out->dev;
2809 int ret = -ENOSYS;
2810
2811 ALOGV("%s", __func__);
2812 pthread_mutex_lock(&adev->lock);
2813 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2814 out->playback_started && out->pcm != NULL) {
2815 pcm_stop(out->pcm);
2816 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002817 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002818 }
2819 pthread_mutex_unlock(&adev->lock);
2820 return ret;
2821}
2822
2823static int out_start(const struct audio_stream_out* stream)
2824{
2825 struct stream_out *out = (struct stream_out *)stream;
2826 struct audio_device *adev = out->dev;
2827 int ret = -ENOSYS;
2828
2829 ALOGV("%s", __func__);
2830 pthread_mutex_lock(&adev->lock);
2831 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2832 !out->playback_started && out->pcm != NULL) {
2833 ret = start_output_stream(out);
2834 if (ret == 0) {
2835 out->playback_started = true;
2836 }
2837 }
2838 pthread_mutex_unlock(&adev->lock);
2839 return ret;
2840}
2841
Phil Burkbc991042017-02-24 08:06:44 -08002842/*
2843 * Modify config->period_count based on min_size_frames
2844 */
2845static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2846{
2847 int periodCountRequested = (min_size_frames + config->period_size - 1)
2848 / config->period_size;
2849 int periodCount = MMAP_PERIOD_COUNT_MIN;
2850
2851 ALOGV("%s original config.period_size = %d config.period_count = %d",
2852 __func__, config->period_size, config->period_count);
2853
2854 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2855 periodCount *= 2;
2856 }
2857 config->period_count = periodCount;
2858
2859 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2860}
2861
Eric Laurent0e46adf2016-12-16 12:49:24 -08002862static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2863 int32_t min_size_frames,
2864 struct audio_mmap_buffer_info *info)
2865{
2866 struct stream_out *out = (struct stream_out *)stream;
2867 struct audio_device *adev = out->dev;
2868 int ret = 0;
2869 unsigned int offset1;
2870 unsigned int frames1;
2871 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002872 uint32_t mmap_size;
2873 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002874
2875 ALOGV("%s", __func__);
2876 pthread_mutex_lock(&adev->lock);
2877
2878 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002879 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002880 ret = -EINVAL;
2881 goto exit;
2882 }
2883 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002884 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002885 ret = -ENOSYS;
2886 goto exit;
2887 }
2888 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2889 if (out->pcm_device_id < 0) {
2890 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2891 __func__, out->pcm_device_id, out->usecase);
2892 ret = -EINVAL;
2893 goto exit;
2894 }
Phil Burkbc991042017-02-24 08:06:44 -08002895
2896 adjust_mmap_period_count(&out->config, min_size_frames);
2897
Eric Laurent0e46adf2016-12-16 12:49:24 -08002898 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2899 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2900 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2901 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2902 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2903 step = "open";
2904 ret = -ENODEV;
2905 goto exit;
2906 }
2907 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2908 if (ret < 0) {
2909 step = "begin";
2910 goto exit;
2911 }
2912 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002913 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002914 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002915 ret = platform_get_mmap_data_fd(adev->platform,
2916 out->pcm_device_id, 0 /*playback*/,
2917 &info->shared_memory_fd,
2918 &mmap_size);
2919 if (ret < 0) {
2920 // Fall back to non exclusive mode
2921 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2922 } else {
2923 if (mmap_size < buffer_size) {
2924 step = "mmap";
2925 goto exit;
2926 }
2927 // FIXME: indicate exclusive mode support by returning a negative buffer size
2928 info->buffer_size_frames *= -1;
2929 }
2930 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002931
2932 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2933 if (ret < 0) {
2934 step = "commit";
2935 goto exit;
2936 }
Phil Burkbc991042017-02-24 08:06:44 -08002937
2938 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002939 ret = 0;
2940
2941 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2942 __func__, info->shared_memory_address, info->buffer_size_frames);
2943
2944exit:
2945 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002946 if (out->pcm == NULL) {
2947 ALOGE("%s: %s - %d", __func__, step, ret);
2948 } else {
2949 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002950 pcm_close(out->pcm);
2951 out->pcm = NULL;
2952 }
2953 }
2954 pthread_mutex_unlock(&adev->lock);
2955 return ret;
2956}
2957
2958static int out_get_mmap_position(const struct audio_stream_out *stream,
2959 struct audio_mmap_position *position)
2960{
2961 struct stream_out *out = (struct stream_out *)stream;
2962 ALOGVV("%s", __func__);
2963 if (position == NULL) {
2964 return -EINVAL;
2965 }
2966 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2967 return -ENOSYS;
2968 }
2969 if (out->pcm == NULL) {
2970 return -ENOSYS;
2971 }
2972
2973 struct timespec ts = { 0, 0 };
2974 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2975 if (ret < 0) {
2976 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2977 return ret;
2978 }
Andy Hungfc044e12017-03-20 09:24:22 -07002979 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002980 return 0;
2981}
2982
2983
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984/** audio_stream_in implementation **/
2985static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2986{
2987 struct stream_in *in = (struct stream_in *)stream;
2988
2989 return in->config.rate;
2990}
2991
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002992static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993{
2994 return -ENOSYS;
2995}
2996
2997static size_t in_get_buffer_size(const struct audio_stream *stream)
2998{
2999 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003000 return in->config.period_size * in->af_period_multiplier *
3001 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002}
3003
3004static uint32_t in_get_channels(const struct audio_stream *stream)
3005{
3006 struct stream_in *in = (struct stream_in *)stream;
3007
3008 return in->channel_mask;
3009}
3010
vivek mehta4ed66e62016-04-15 23:33:34 -07003011static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012{
vivek mehta4ed66e62016-04-15 23:33:34 -07003013 struct stream_in *in = (struct stream_in *)stream;
3014 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015}
3016
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003017static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018{
3019 return -ENOSYS;
3020}
3021
3022static int in_standby(struct audio_stream *stream)
3023{
3024 struct stream_in *in = (struct stream_in *)stream;
3025 struct audio_device *adev = in->dev;
3026 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003027 bool do_stop = true;
3028
Eric Laurent994a6932013-07-17 11:51:42 -07003029 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003030
3031 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003032
3033 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003034 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003035 audio_extn_sound_trigger_stop_lab(in);
3036 in->standby = true;
3037 }
3038
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003040 if (adev->adm_deregister_stream)
3041 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3042
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003043 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003045 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003046 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003047 in->capture_started = false;
3048 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003049 if (in->pcm) {
3050 pcm_close(in->pcm);
3051 in->pcm = NULL;
3052 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003053 adev->enable_voicerx = false;
3054 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003055 if (do_stop) {
3056 status = stop_input_stream(in);
3057 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003058 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 }
3060 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003061 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062 return status;
3063}
3064
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003065static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066{
3067 return 0;
3068}
3069
3070static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3071{
3072 struct stream_in *in = (struct stream_in *)stream;
3073 struct audio_device *adev = in->dev;
3074 struct str_parms *parms;
3075 char *str;
3076 char value[32];
3077 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003078 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079
Eric Laurent994a6932013-07-17 11:51:42 -07003080 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003081 parms = str_parms_create_str(kvpairs);
3082
3083 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3084
Eric Laurenta1478072015-09-21 17:21:52 -07003085 lock_input_stream(in);
3086
Eric Laurent150dbfe2013-02-27 14:31:02 -08003087 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 if (ret >= 0) {
3089 val = atoi(value);
3090 /* no audio source uses val == 0 */
3091 if ((in->source != val) && (val != 0)) {
3092 in->source = val;
3093 }
3094 }
3095
3096 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003097
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 if (ret >= 0) {
3099 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003100 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101 in->device = val;
3102 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003103 if (!in->standby) {
3104 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003105 // inform adm before actual routing to prevent glitches.
3106 if (adev->adm_on_routing_change) {
3107 adev->adm_on_routing_change(adev->adm_data,
3108 in->capture_handle);
3109 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003110 select_devices(adev, in->usecase);
3111 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 }
3113 }
3114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003116 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117
3118 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003119 ALOGV("%s: exit: status(%d)", __func__, status);
3120 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121}
3122
Haynes Mathew George569b7482017-05-08 14:44:27 -07003123static char* in_get_parameters(const struct audio_stream *stream,
3124 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003126 struct stream_in *in = (struct stream_in *)stream;
3127 struct str_parms *query = str_parms_create_str(keys);
3128 char *str;
3129 struct str_parms *reply = str_parms_create();
3130 bool replied = false;
3131
3132 ALOGV("%s: enter: keys - %s", __func__, keys);
3133 replied |= stream_get_parameter_channels(query, reply,
3134 &in->supported_channel_masks[0]);
3135 replied |= stream_get_parameter_formats(query, reply,
3136 &in->supported_formats[0]);
3137 replied |= stream_get_parameter_rates(query, reply,
3138 &in->supported_sample_rates[0]);
3139 if (replied) {
3140 str = str_parms_to_str(reply);
3141 } else {
3142 str = strdup(keys);
3143 }
3144 str_parms_destroy(query);
3145 str_parms_destroy(reply);
3146 ALOGV("%s: exit: returns - %s", __func__, str);
3147 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148}
3149
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003150static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003152 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153}
3154
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003155static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3156{
3157 if (!stream || !parms)
3158 return;
3159
3160 struct stream_in *in = (struct stream_in *)stream;
3161 struct audio_device *adev = in->dev;
3162
3163 card_status_t status;
3164 int card;
3165 if (parse_snd_card_status(parms, &card, &status) < 0)
3166 return;
3167
3168 pthread_mutex_lock(&adev->lock);
3169 bool valid_cb = (card == adev->snd_card);
3170 pthread_mutex_unlock(&adev->lock);
3171
3172 if (!valid_cb)
3173 return;
3174
3175 lock_input_stream(in);
3176 if (in->card_status != status)
3177 in->card_status = status;
3178 pthread_mutex_unlock(&in->lock);
3179
3180 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3181 use_case_table[in->usecase],
3182 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3183
3184 // a better solution would be to report error back to AF and let
3185 // it put the stream to standby
3186 if (status == CARD_STATUS_OFFLINE)
3187 in_standby(&in->stream.common);
3188
3189 return;
3190}
3191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3193 size_t bytes)
3194{
3195 struct stream_in *in = (struct stream_in *)stream;
3196 struct audio_device *adev = in->dev;
3197 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003198 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199
Eric Laurenta1478072015-09-21 17:21:52 -07003200 lock_input_stream(in);
Andy Hung928efbe2017-06-12 14:05:22 -07003201 const size_t frame_size = audio_stream_in_frame_size(stream);
3202 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003203
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003204 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003205 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003206 /* Read from sound trigger HAL */
3207 audio_extn_sound_trigger_read(in, buffer, bytes);
3208 pthread_mutex_unlock(&in->lock);
3209 return bytes;
3210 }
3211
Eric Laurent0e46adf2016-12-16 12:49:24 -08003212 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3213 ret = -ENOSYS;
3214 goto exit;
3215 }
3216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003218 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003220 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222 goto exit;
3223 }
3224 in->standby = 0;
3225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226
Haynes Mathew George03c40102016-01-29 17:57:48 -08003227 //what's the duration requested by the client?
3228 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3229 in->config.rate;
3230 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003231
Haynes Mathew George03c40102016-01-29 17:57:48 -08003232 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003234 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003235 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003236 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003237 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003238 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003239 if (ret < 0) {
3240 ALOGE("Failed to read w/err %s", strerror(errno));
3241 ret = -errno;
3242 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003243 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3244 if (bytes % 4 == 0) {
3245 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3246 int_buf_stream = buffer;
3247 for (size_t itt=0; itt < bytes/4 ; itt++) {
3248 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003249 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003250 } else {
3251 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3252 ret = -EINVAL;
3253 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003254 }
3255 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003256 }
3257
Haynes Mathew George03c40102016-01-29 17:57:48 -08003258 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003260 /*
3261 * Instead of writing zeroes here, we could trust the hardware
3262 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003263 * 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 -08003264 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003265 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266 memset(buffer, 0, bytes);
3267
3268exit:
3269 pthread_mutex_unlock(&in->lock);
3270
3271 if (ret != 0) {
3272 in_standby(&in->stream.common);
3273 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung928efbe2017-06-12 14:05:22 -07003274 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003275 memset(buffer, 0, bytes); // clear return data
3276 }
3277 if (bytes > 0) {
Andy Hung928efbe2017-06-12 14:05:22 -07003278 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 }
3280 return bytes;
3281}
3282
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003283static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284{
3285 return 0;
3286}
3287
Andy Hung6ebe5962016-01-15 17:46:57 -08003288static int in_get_capture_position(const struct audio_stream_in *stream,
3289 int64_t *frames, int64_t *time)
3290{
3291 if (stream == NULL || frames == NULL || time == NULL) {
3292 return -EINVAL;
3293 }
3294 struct stream_in *in = (struct stream_in *)stream;
3295 int ret = -ENOSYS;
3296
3297 lock_input_stream(in);
3298 if (in->pcm) {
3299 struct timespec timestamp;
3300 unsigned int avail;
3301 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3302 *frames = in->frames_read + avail;
3303 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3304 ret = 0;
3305 }
3306 }
3307 pthread_mutex_unlock(&in->lock);
3308 return ret;
3309}
3310
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003311static int add_remove_audio_effect(const struct audio_stream *stream,
3312 effect_handle_t effect,
3313 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003315 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003316 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003317 int status = 0;
3318 effect_descriptor_t desc;
3319
3320 status = (*effect)->get_descriptor(effect, &desc);
3321 if (status != 0)
3322 return status;
3323
Eric Laurenta1478072015-09-21 17:21:52 -07003324 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003325 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003326 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003327 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003328 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003329 in->enable_aec != enable &&
3330 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3331 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003332 if (!enable)
3333 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003334 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3335 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3336 adev->enable_voicerx = enable;
3337 struct audio_usecase *usecase;
3338 struct listnode *node;
3339 list_for_each(node, &adev->usecase_list) {
3340 usecase = node_to_item(node, struct audio_usecase, list);
3341 if (usecase->type == PCM_PLAYBACK) {
3342 select_devices(adev, usecase->id);
3343 break;
3344 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003345 }
3346 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003347 if (!in->standby)
3348 select_devices(in->dev, in->usecase);
3349 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003350 if (in->enable_ns != enable &&
3351 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3352 in->enable_ns = enable;
3353 if (!in->standby)
3354 select_devices(in->dev, in->usecase);
3355 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003356 pthread_mutex_unlock(&in->dev->lock);
3357 pthread_mutex_unlock(&in->lock);
3358
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359 return 0;
3360}
3361
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003362static int in_add_audio_effect(const struct audio_stream *stream,
3363 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003364{
Eric Laurent994a6932013-07-17 11:51:42 -07003365 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003366 return add_remove_audio_effect(stream, effect, true);
3367}
3368
3369static int in_remove_audio_effect(const struct audio_stream *stream,
3370 effect_handle_t effect)
3371{
Eric Laurent994a6932013-07-17 11:51:42 -07003372 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003373 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374}
3375
Eric Laurent0e46adf2016-12-16 12:49:24 -08003376static int in_stop(const struct audio_stream_in* stream)
3377{
3378 struct stream_in *in = (struct stream_in *)stream;
3379 struct audio_device *adev = in->dev;
3380
3381 int ret = -ENOSYS;
3382 ALOGV("%s", __func__);
3383 pthread_mutex_lock(&adev->lock);
3384 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3385 in->capture_started && in->pcm != NULL) {
3386 pcm_stop(in->pcm);
3387 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003388 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003389 }
3390 pthread_mutex_unlock(&adev->lock);
3391 return ret;
3392}
3393
3394static int in_start(const struct audio_stream_in* stream)
3395{
3396 struct stream_in *in = (struct stream_in *)stream;
3397 struct audio_device *adev = in->dev;
3398 int ret = -ENOSYS;
3399
3400 ALOGV("%s in %p", __func__, in);
3401 pthread_mutex_lock(&adev->lock);
3402 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3403 !in->capture_started && in->pcm != NULL) {
3404 if (!in->capture_started) {
3405 ret = start_input_stream(in);
3406 if (ret == 0) {
3407 in->capture_started = true;
3408 }
3409 }
3410 }
3411 pthread_mutex_unlock(&adev->lock);
3412 return ret;
3413}
3414
3415static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3416 int32_t min_size_frames,
3417 struct audio_mmap_buffer_info *info)
3418{
3419 struct stream_in *in = (struct stream_in *)stream;
3420 struct audio_device *adev = in->dev;
3421 int ret = 0;
3422 unsigned int offset1;
3423 unsigned int frames1;
3424 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003425 uint32_t mmap_size;
3426 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003427
3428 pthread_mutex_lock(&adev->lock);
3429 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003430
Eric Laurent0e46adf2016-12-16 12:49:24 -08003431 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003432 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003433 ret = -EINVAL;
3434 goto exit;
3435 }
3436 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003437 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003438 ALOGV("%s in %p", __func__, in);
3439 ret = -ENOSYS;
3440 goto exit;
3441 }
3442 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3443 if (in->pcm_device_id < 0) {
3444 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3445 __func__, in->pcm_device_id, in->usecase);
3446 ret = -EINVAL;
3447 goto exit;
3448 }
Phil Burkbc991042017-02-24 08:06:44 -08003449
3450 adjust_mmap_period_count(&in->config, min_size_frames);
3451
Eric Laurent0e46adf2016-12-16 12:49:24 -08003452 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3453 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3454 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3455 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3456 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3457 step = "open";
3458 ret = -ENODEV;
3459 goto exit;
3460 }
3461
3462 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3463 if (ret < 0) {
3464 step = "begin";
3465 goto exit;
3466 }
3467 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003468 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003469 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003470 ret = platform_get_mmap_data_fd(adev->platform,
3471 in->pcm_device_id, 1 /*capture*/,
3472 &info->shared_memory_fd,
3473 &mmap_size);
3474 if (ret < 0) {
3475 // Fall back to non exclusive mode
3476 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3477 } else {
3478 if (mmap_size < buffer_size) {
3479 step = "mmap";
3480 goto exit;
3481 }
3482 // FIXME: indicate exclusive mode support by returning a negative buffer size
3483 info->buffer_size_frames *= -1;
3484 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003485
Haynes Mathew George96483a22017-03-28 14:52:47 -07003486 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003487
3488 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3489 if (ret < 0) {
3490 step = "commit";
3491 goto exit;
3492 }
3493
Phil Burkbc991042017-02-24 08:06:44 -08003494 in->standby = false;
3495 ret = 0;
3496
Eric Laurent0e46adf2016-12-16 12:49:24 -08003497 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3498 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003499
3500exit:
3501 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003502 if (in->pcm == NULL) {
3503 ALOGE("%s: %s - %d", __func__, step, ret);
3504 } else {
3505 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003506 pcm_close(in->pcm);
3507 in->pcm = NULL;
3508 }
3509 }
3510 pthread_mutex_unlock(&adev->lock);
3511 return ret;
3512}
3513
3514static int in_get_mmap_position(const struct audio_stream_in *stream,
3515 struct audio_mmap_position *position)
3516{
3517 struct stream_in *in = (struct stream_in *)stream;
3518 ALOGVV("%s", __func__);
3519 if (position == NULL) {
3520 return -EINVAL;
3521 }
3522 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3523 return -ENOSYS;
3524 }
3525 if (in->pcm == NULL) {
3526 return -ENOSYS;
3527 }
3528 struct timespec ts = { 0, 0 };
3529 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3530 if (ret < 0) {
3531 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3532 return ret;
3533 }
Andy Hungfc044e12017-03-20 09:24:22 -07003534 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003535 return 0;
3536}
3537
3538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539static int adev_open_output_stream(struct audio_hw_device *dev,
3540 audio_io_handle_t handle,
3541 audio_devices_t devices,
3542 audio_output_flags_t flags,
3543 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003544 struct audio_stream_out **stream_out,
3545 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546{
3547 struct audio_device *adev = (struct audio_device *)dev;
3548 struct stream_out *out;
3549 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003550 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3551 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3552 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3553 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003554
Eric Laurent994a6932013-07-17 11:51:42 -07003555 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 __func__, config->sample_rate, config->channel_mask, devices, flags);
3557 *stream_out = NULL;
3558 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3559
3560 if (devices == AUDIO_DEVICE_NONE)
3561 devices = AUDIO_DEVICE_OUT_SPEAKER;
3562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 out->flags = flags;
3564 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003565 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003566 out->format = config->format;
3567 out->sample_rate = config->sample_rate;
3568 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3569 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003570 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003571
3572 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003573 if (audio_is_linear_pcm(out->format) &&
3574 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003575 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003576 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003577 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003578 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003579 if (config->sample_rate == 0)
3580 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3581 if (config->channel_mask == 0)
3582 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3583 if (config->format == AUDIO_FORMAT_DEFAULT)
3584 config->format = AUDIO_FORMAT_PCM_16_BIT;
3585 } else if (is_usb_dev) {
3586 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3587 &config->format,
3588 &out->supported_formats[0],
3589 MAX_SUPPORTED_FORMATS,
3590 &config->channel_mask,
3591 &out->supported_channel_masks[0],
3592 MAX_SUPPORTED_CHANNEL_MASKS,
3593 &config->sample_rate,
3594 &out->supported_sample_rates[0],
3595 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003596 ALOGV("plugged dev USB ret %d", ret);
3597 } else {
3598 ret = -1;
3599 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003600 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003601 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003602 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003603
Haynes Mathew George569b7482017-05-08 14:44:27 -07003604 out->channel_mask = config->channel_mask;
3605 out->sample_rate = config->sample_rate;
3606 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003607 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3608 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003609 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003610 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003611 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003612 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3613 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003614 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003615 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003616 pthread_mutex_lock(&adev->lock);
3617 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3618 pthread_mutex_unlock(&adev->lock);
3619
3620 // reject offload during card offline to allow
3621 // fallback to s/w paths
3622 if (offline) {
3623 ret = -ENODEV;
3624 goto error_open;
3625 }
3626
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003627 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3628 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3629 ALOGE("%s: Unsupported Offload information", __func__);
3630 ret = -EINVAL;
3631 goto error_open;
3632 }
3633 if (!is_supported_format(config->offload_info.format)) {
3634 ALOGE("%s: Unsupported audio format", __func__);
3635 ret = -EINVAL;
3636 goto error_open;
3637 }
3638
3639 out->compr_config.codec = (struct snd_codec *)
3640 calloc(1, sizeof(struct snd_codec));
3641
3642 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3643 if (config->offload_info.channel_mask)
3644 out->channel_mask = config->offload_info.channel_mask;
3645 else if (config->channel_mask)
3646 out->channel_mask = config->channel_mask;
3647 out->format = config->offload_info.format;
3648 out->sample_rate = config->offload_info.sample_rate;
3649
3650 out->stream.set_callback = out_set_callback;
3651 out->stream.pause = out_pause;
3652 out->stream.resume = out_resume;
3653 out->stream.drain = out_drain;
3654 out->stream.flush = out_flush;
3655
3656 out->compr_config.codec->id =
3657 get_snd_codec_id(config->offload_info.format);
3658 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3659 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003660 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003661 out->compr_config.codec->bit_rate =
3662 config->offload_info.bit_rate;
3663 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003664 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003665 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3666
3667 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3668 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003669
3670 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003671 create_offload_callback_thread(out);
3672 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3673 __func__, config->offload_info.version,
3674 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003675 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003676 switch (config->sample_rate) {
3677 case 8000:
3678 case 16000:
3679 case 48000:
3680 out->sample_rate = config->sample_rate;
3681 break;
3682 default:
3683 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003684 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003685 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003686 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3687 out->config = pcm_config_afe_proxy_playback;
3688 adev->voice_tx_output = out;
vivek mehtaa68fea62017-06-08 19:04:02 -07003689 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3690 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3691 AUDIO_OUTPUT_FLAG_VOIP_RX))) {
3692 uint32_t buffer_size, frame_size;
3693 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3694 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3695 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3696 out->config = pcm_config_voip;
3697 out->config.format = pcm_format_from_audio_format(config->format);
3698 out->config.rate = config->sample_rate;
3699 out->config.channels =
3700 audio_channel_count_from_out_mask(config->channel_mask);
3701 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3702 config->sample_rate,
3703 config->format,
3704 out->config.channels,
3705 false /*is_low_latency*/);
3706 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3707 out->config.period_size = buffer_size / frame_size;
3708 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3709 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003710 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003711 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3712 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3713 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003714 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3715 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3716 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003717 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3718 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003719 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003720 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003721 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3722 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3723 out->config = pcm_config_mmap_playback;
3724 out->stream.start = out_start;
3725 out->stream.stop = out_stop;
3726 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3727 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003728 } else {
3729 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3730 out->config = pcm_config_low_latency;
3731 }
3732 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003733 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003734 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003735 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003737
3738 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3739 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3740 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3741 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3742 __func__, config->sample_rate, config->format, config->channel_mask);
3743 config->sample_rate = out->sample_rate;
3744 config->format = out->format;
3745 config->channel_mask = out->channel_mask;
3746 ret = -EINVAL;
3747 goto error_open;
3748 }
3749
Andy Hung6fcba9c2014-03-18 11:53:32 -07003750 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3751 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003753 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003754 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003755 adev->primary_output = out;
3756 else {
3757 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003758 ret = -EEXIST;
3759 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003760 }
3761 }
3762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 /* Check if this usecase is already existing */
3764 pthread_mutex_lock(&adev->lock);
3765 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3766 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003768 ret = -EEXIST;
3769 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 }
3771 pthread_mutex_unlock(&adev->lock);
3772
3773 out->stream.common.get_sample_rate = out_get_sample_rate;
3774 out->stream.common.set_sample_rate = out_set_sample_rate;
3775 out->stream.common.get_buffer_size = out_get_buffer_size;
3776 out->stream.common.get_channels = out_get_channels;
3777 out->stream.common.get_format = out_get_format;
3778 out->stream.common.set_format = out_set_format;
3779 out->stream.common.standby = out_standby;
3780 out->stream.common.dump = out_dump;
3781 out->stream.common.set_parameters = out_set_parameters;
3782 out->stream.common.get_parameters = out_get_parameters;
3783 out->stream.common.add_audio_effect = out_add_audio_effect;
3784 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3785 out->stream.get_latency = out_get_latency;
3786 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003787#ifdef NO_AUDIO_OUT
3788 out->stream.write = out_write_for_no_output;
3789#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003791#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003792 out->stream.get_render_position = out_get_render_position;
3793 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003794 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795
Eric Laurent0e46adf2016-12-16 12:49:24 -08003796 if (out->realtime)
3797 out->af_period_multiplier = af_period_multiplier;
3798 else
3799 out->af_period_multiplier = 1;
3800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003802 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003803 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003805 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003806 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003807 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 config->format = out->stream.common.get_format(&out->stream.common);
3810 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3811 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3812
Andy Hunga452b0a2017-03-15 14:51:15 -07003813 out->error_log = error_log_create(
3814 ERROR_LOG_ENTRIES,
3815 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3816
Andy Hungfc044e12017-03-20 09:24:22 -07003817 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003818 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003819 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003820 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3821 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3822
3823 out->power_log = power_log_create(
3824 config->sample_rate,
3825 audio_channel_count_from_out_mask(config->channel_mask),
3826 config->format,
3827 POWER_LOG_ENTRIES,
3828 POWER_LOG_FRAMES_PER_ENTRY);
3829 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003830
3831 /*
3832 By locking output stream before registering, we allow the callback
3833 to update stream's state only after stream's initial state is set to
3834 adev state.
3835 */
3836 lock_output_stream(out);
3837 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3838 pthread_mutex_lock(&adev->lock);
3839 out->card_status = adev->card_status;
3840 pthread_mutex_unlock(&adev->lock);
3841 pthread_mutex_unlock(&out->lock);
3842
vivek mehta4a824772017-06-08 19:05:49 -07003843 stream_app_type_cfg_init(&out->app_type_cfg);
3844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003845 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003846
Eric Laurent994a6932013-07-17 11:51:42 -07003847 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003849
3850error_open:
3851 free(out);
3852 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003853 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003854 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855}
3856
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003857static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858 struct audio_stream_out *stream)
3859{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003860 struct stream_out *out = (struct stream_out *)stream;
3861 struct audio_device *adev = out->dev;
3862
Eric Laurent994a6932013-07-17 11:51:42 -07003863 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003864
3865 // must deregister from sndmonitor first to prevent races
3866 // between the callback and close_stream
3867 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003869 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3870 destroy_offload_callback_thread(out);
3871
3872 if (out->compr_config.codec != NULL)
3873 free(out->compr_config.codec);
3874 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003875
3876 if (adev->voice_tx_output == out)
3877 adev->voice_tx_output = NULL;
3878
Andy Hungfc044e12017-03-20 09:24:22 -07003879 power_log_destroy(out->power_log);
3880 out->power_log = NULL;
3881
Andy Hunga452b0a2017-03-15 14:51:15 -07003882 error_log_destroy(out->error_log);
3883 out->error_log = NULL;
3884
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003885 pthread_cond_destroy(&out->cond);
3886 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003888 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889}
3890
3891static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3892{
3893 struct audio_device *adev = (struct audio_device *)dev;
3894 struct str_parms *parms;
3895 char *str;
3896 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003897 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003899 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900
Joe Onorato188b6222016-03-01 11:02:27 -08003901 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003902
3903 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904
3905 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003906 status = voice_set_parameters(adev, parms);
3907 if (status != 0) {
3908 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003909 }
3910
3911 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3912 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003913 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3915 adev->bluetooth_nrec = true;
3916 else
3917 adev->bluetooth_nrec = false;
3918 }
3919
3920 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3921 if (ret >= 0) {
3922 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3923 adev->screen_off = false;
3924 else
3925 adev->screen_off = true;
3926 }
3927
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003928 ret = str_parms_get_int(parms, "rotation", &val);
3929 if (ret >= 0) {
3930 bool reverse_speakers = false;
3931 switch(val) {
3932 // FIXME: note that the code below assumes that the speakers are in the correct placement
3933 // relative to the user when the device is rotated 90deg from its default rotation. This
3934 // assumption is device-specific, not platform-specific like this code.
3935 case 270:
3936 reverse_speakers = true;
3937 break;
3938 case 0:
3939 case 90:
3940 case 180:
3941 break;
3942 default:
3943 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003944 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003945 }
Eric Laurent03f09432014-03-25 18:09:11 -07003946 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07003947 // check and set swap
3948 // - check if orientation changed and speaker active
3949 // - set rotation and cache the rotation value
3950 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003951 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003952 }
3953
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003954 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3955 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003956 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003957 }
3958
David Linee3fe402017-03-13 10:00:42 -07003959 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3960 if (ret >= 0) {
3961 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003962 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003963 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3964 if (ret >= 0) {
3965 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003966 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003967 }
Eric Laurent99dab492017-06-17 15:19:08 -07003968 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003969 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3970 if (ret >= 0) {
3971 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003972 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003973 }
3974 }
3975 }
3976
3977 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3978 if (ret >= 0) {
3979 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003980 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003981 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3982 if (ret >= 0) {
3983 const int card = atoi(value);
3984
Eric Laurent99dab492017-06-17 15:19:08 -07003985 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003986 }
Eric Laurent99dab492017-06-17 15:19:08 -07003987 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003988 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3989 if (ret >= 0) {
3990 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003991 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003992 }
3993 }
3994 }
3995
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003996 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003997done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003999 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004000 ALOGV("%s: exit with code(%d)", __func__, status);
4001 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004002}
4003
4004static char* adev_get_parameters(const struct audio_hw_device *dev,
4005 const char *keys)
4006{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004007 struct audio_device *adev = (struct audio_device *)dev;
4008 struct str_parms *reply = str_parms_create();
4009 struct str_parms *query = str_parms_create_str(keys);
4010 char *str;
4011
4012 pthread_mutex_lock(&adev->lock);
4013
4014 voice_get_parameters(adev, query, reply);
4015 str = str_parms_to_str(reply);
4016 str_parms_destroy(query);
4017 str_parms_destroy(reply);
4018
4019 pthread_mutex_unlock(&adev->lock);
4020 ALOGV("%s: exit: returns - %s", __func__, str);
4021 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022}
4023
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004024static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004025{
4026 return 0;
4027}
4028
Haynes Mathew George5191a852013-09-11 14:19:36 -07004029static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4030{
4031 int ret;
4032 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004033
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004034 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4035
Haynes Mathew George5191a852013-09-11 14:19:36 -07004036 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004037 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004038 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004039
Haynes Mathew George5191a852013-09-11 14:19:36 -07004040 return ret;
4041}
4042
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004043static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004044{
4045 return -ENOSYS;
4046}
4047
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004048static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4049 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050{
4051 return -ENOSYS;
4052}
4053
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004054static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055{
4056 return -ENOSYS;
4057}
4058
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004059static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060{
4061 return -ENOSYS;
4062}
4063
4064static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4065{
4066 struct audio_device *adev = (struct audio_device *)dev;
4067
4068 pthread_mutex_lock(&adev->lock);
4069 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004070 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004072 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4073 voice_is_in_call(adev)) {
4074 voice_stop_call(adev);
4075 adev->current_call_output = NULL;
4076 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077 }
4078 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004079
4080 audio_extn_extspk_set_mode(adev->extspk, mode);
4081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004082 return 0;
4083}
4084
4085static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4086{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004087 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089
Eric Laurent2bafff12016-03-17 12:17:23 -07004090 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004091 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004092 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4093 ret = audio_extn_hfp_set_mic_mute(adev, state);
4094 } else {
4095 ret = voice_set_mic_mute(adev, state);
4096 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004097 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004098 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004099
4100 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101}
4102
4103static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4104{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004105 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106 return 0;
4107}
4108
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004109static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110 const struct audio_config *config)
4111{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004112 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113
Eric Laurent74b55762017-07-09 17:04:53 -07004114 /* Don't know if USB HIFI in this context so use true to be conservative */
4115 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4116 true /*is_usb_hifi */) != 0)
4117 return 0;
4118
vivek mehtaa68fea62017-06-08 19:04:02 -07004119 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4120 config->sample_rate, config->format,
4121 channel_count,
4122 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123}
4124
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004125static bool adev_input_allow_hifi_record(struct audio_device *adev,
4126 audio_devices_t devices,
4127 audio_input_flags_t flags,
4128 audio_source_t source) {
4129 const bool allowed = true;
4130
4131 if (!audio_is_usb_in_device(devices))
4132 return !allowed;
4133
4134 switch (flags) {
4135 case AUDIO_INPUT_FLAG_NONE:
4136 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4137 break;
4138 default:
4139 return !allowed;
4140 }
4141
4142 switch (source) {
4143 case AUDIO_SOURCE_DEFAULT:
4144 case AUDIO_SOURCE_MIC:
4145 case AUDIO_SOURCE_UNPROCESSED:
4146 break;
4147 default:
4148 return !allowed;
4149 }
4150
4151 switch (adev->mode) {
4152 case 0:
4153 break;
4154 default:
4155 return !allowed;
4156 }
4157
4158 return allowed;
4159}
4160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004162 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 audio_devices_t devices,
4164 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004165 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004166 audio_input_flags_t flags,
4167 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004168 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169{
4170 struct audio_device *adev = (struct audio_device *)dev;
4171 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004172 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004173 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004174 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004175 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004176 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4177 devices,
4178 flags,
4179 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004180 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004182
Eric Laurent74b55762017-07-09 17:04:53 -07004183 if (!(is_usb_dev && may_use_hifi_record)) {
4184 if (config->sample_rate == 0)
4185 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4186 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4187 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4188 if (config->format == AUDIO_FORMAT_DEFAULT)
4189 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004190
Eric Laurent74b55762017-07-09 17:04:53 -07004191 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4192
4193 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4194 return -EINVAL;
4195 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004197 if (audio_extn_tfa_98xx_is_supported() &&
4198 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004199 return -EINVAL;
4200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4202
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004203 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004204 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206 in->stream.common.get_sample_rate = in_get_sample_rate;
4207 in->stream.common.set_sample_rate = in_set_sample_rate;
4208 in->stream.common.get_buffer_size = in_get_buffer_size;
4209 in->stream.common.get_channels = in_get_channels;
4210 in->stream.common.get_format = in_get_format;
4211 in->stream.common.set_format = in_set_format;
4212 in->stream.common.standby = in_standby;
4213 in->stream.common.dump = in_dump;
4214 in->stream.common.set_parameters = in_set_parameters;
4215 in->stream.common.get_parameters = in_get_parameters;
4216 in->stream.common.add_audio_effect = in_add_audio_effect;
4217 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4218 in->stream.set_gain = in_set_gain;
4219 in->stream.read = in_read;
4220 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004221 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222
4223 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004224 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004225 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004227 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004228 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229
Haynes Mathew George569b7482017-05-08 14:44:27 -07004230 if (is_usb_dev && may_use_hifi_record) {
4231 /* HiFi record selects an appropriate format, channel, rate combo
4232 depending on sink capabilities*/
4233 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4234 &config->format,
4235 &in->supported_formats[0],
4236 MAX_SUPPORTED_FORMATS,
4237 &config->channel_mask,
4238 &in->supported_channel_masks[0],
4239 MAX_SUPPORTED_CHANNEL_MASKS,
4240 &config->sample_rate,
4241 &in->supported_sample_rates[0],
4242 MAX_SUPPORTED_SAMPLE_RATES);
4243 if (ret != 0) {
4244 ret = -EINVAL;
4245 goto err_open;
4246 }
Eric Laurent74b55762017-07-09 17:04:53 -07004247 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004248 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004249 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004250 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4251 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4252 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4253 bool ret_error = false;
4254 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4255 from HAL is 8_24
4256 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4257 8_24 return error indicating supported format is 8_24
4258 *> In case of any other source requesting 24 bit or float return error
4259 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004260
vivek mehta57ff9b52016-04-28 14:13:08 -07004261 on error flinger will retry with supported format passed
4262 */
4263 if (source != AUDIO_SOURCE_UNPROCESSED) {
4264 config->format = AUDIO_FORMAT_PCM_16_BIT;
4265 ret_error = true;
4266 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4267 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4268 ret_error = true;
4269 }
4270
4271 if (ret_error) {
4272 ret = -EINVAL;
4273 goto err_open;
4274 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004275 }
4276
vivek mehta57ff9b52016-04-28 14:13:08 -07004277 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004278 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004281 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4282 if (config->sample_rate == 0)
4283 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4284 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4285 config->sample_rate != 8000) {
4286 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4287 ret = -EINVAL;
4288 goto err_open;
4289 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004290
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004291 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4292 config->format = AUDIO_FORMAT_PCM_16_BIT;
4293 ret = -EINVAL;
4294 goto err_open;
4295 }
4296
4297 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4298 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004299 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004300 } else if (is_usb_dev && may_use_hifi_record) {
4301 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4302 in->config = pcm_config_audio_capture;
4303 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004304 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4305 config->sample_rate,
4306 config->format,
4307 channel_count,
4308 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004309 in->config.period_size = buffer_size / frame_size;
4310 in->config.rate = config->sample_rate;
4311 in->af_period_multiplier = 1;
4312 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004313 } else {
4314 in->usecase = USECASE_AUDIO_RECORD;
4315 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004316 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004317 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004318#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004319 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004320#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004321 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004322 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004323 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004324 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004325 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4326 config->sample_rate,
4327 config->format,
4328 channel_count,
4329 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004330 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004331 in->config.rate = config->sample_rate;
4332 in->af_period_multiplier = 1;
4333 } else {
4334 // period size is left untouched for rt mode playback
4335 in->config = pcm_config_audio_capture_rt;
4336 in->af_period_multiplier = af_period_multiplier;
4337 }
4338 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4339 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004340 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004341 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4342 in->config = pcm_config_mmap_capture;
4343 in->stream.start = in_start;
4344 in->stream.stop = in_stop;
4345 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4346 in->stream.get_mmap_position = in_get_mmap_position;
4347 in->af_period_multiplier = 1;
4348 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004349 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
4350 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004351 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004352 (config->sample_rate == 8000 ||
4353 config->sample_rate == 16000 ||
4354 config->sample_rate == 32000 ||
4355 config->sample_rate == 48000) &&
4356 channel_count == 1) {
4357 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4358 in->config = pcm_config_audio_capture;
4359 frame_size = audio_stream_in_frame_size(&in->stream);
4360 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4361 config->sample_rate,
4362 config->format,
4363 channel_count, false /*is_low_latency*/);
4364 in->config.period_size = buffer_size / frame_size;
4365 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4366 in->config.rate = config->sample_rate;
4367 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004368 } else {
4369 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004370 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004371 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4372 config->sample_rate,
4373 config->format,
4374 channel_count,
4375 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004376 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004377 in->config.rate = config->sample_rate;
4378 in->af_period_multiplier = 1;
4379 }
4380 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4381 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004382 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004385 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004387 /* This stream could be for sound trigger lab,
4388 get sound trigger pcm if present */
4389 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004391 lock_input_stream(in);
4392 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4393 pthread_mutex_lock(&adev->lock);
4394 in->card_status = adev->card_status;
4395 pthread_mutex_unlock(&adev->lock);
4396 pthread_mutex_unlock(&in->lock);
4397
vivek mehta4a824772017-06-08 19:05:49 -07004398 stream_app_type_cfg_init(&in->app_type_cfg);
4399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004401 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402 return 0;
4403
4404err_open:
4405 free(in);
4406 *stream_in = NULL;
4407 return ret;
4408}
4409
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004410static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411 struct audio_stream_in *stream)
4412{
Eric Laurent994a6932013-07-17 11:51:42 -07004413 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004414
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004415 // must deregister from sndmonitor first to prevent races
4416 // between the callback and close_stream
4417 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418 in_standby(&stream->common);
4419 free(stream);
4420
4421 return;
4422}
4423
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004424static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004425{
4426 return 0;
4427}
4428
Andy Hung31aca912014-03-20 17:14:59 -07004429/* verifies input and output devices and their capabilities.
4430 *
4431 * This verification is required when enabling extended bit-depth or
4432 * sampling rates, as not all qcom products support it.
4433 *
4434 * Suitable for calling only on initialization such as adev_open().
4435 * It fills the audio_device use_case_table[] array.
4436 *
4437 * Has a side-effect that it needs to configure audio routing / devices
4438 * in order to power up the devices and read the device parameters.
4439 * It does not acquire any hw device lock. Should restore the devices
4440 * back to "normal state" upon completion.
4441 */
4442static int adev_verify_devices(struct audio_device *adev)
4443{
4444 /* enumeration is a bit difficult because one really wants to pull
4445 * the use_case, device id, etc from the hidden pcm_device_table[].
4446 * In this case there are the following use cases and device ids.
4447 *
4448 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4449 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004450 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004451 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4452 * [USECASE_AUDIO_RECORD] = {0, 0},
4453 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4454 * [USECASE_VOICE_CALL] = {2, 2},
4455 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004456 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004457 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4458 */
4459
4460 /* should be the usecases enabled in adev_open_input_stream() */
4461 static const int test_in_usecases[] = {
4462 USECASE_AUDIO_RECORD,
4463 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4464 };
4465 /* should be the usecases enabled in adev_open_output_stream()*/
4466 static const int test_out_usecases[] = {
4467 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4468 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4469 };
4470 static const usecase_type_t usecase_type_by_dir[] = {
4471 PCM_PLAYBACK,
4472 PCM_CAPTURE,
4473 };
4474 static const unsigned flags_by_dir[] = {
4475 PCM_OUT,
4476 PCM_IN,
4477 };
4478
4479 size_t i;
4480 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004481 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004482 char info[512]; /* for possible debug info */
4483
4484 for (dir = 0; dir < 2; ++dir) {
4485 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4486 const unsigned flags_dir = flags_by_dir[dir];
4487 const size_t testsize =
4488 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4489 const int *testcases =
4490 dir ? test_in_usecases : test_out_usecases;
4491 const audio_devices_t audio_device =
4492 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4493
4494 for (i = 0; i < testsize; ++i) {
4495 const audio_usecase_t audio_usecase = testcases[i];
4496 int device_id;
4497 snd_device_t snd_device;
4498 struct pcm_params **pparams;
4499 struct stream_out out;
4500 struct stream_in in;
4501 struct audio_usecase uc_info;
4502 int retval;
4503
4504 pparams = &adev->use_case_table[audio_usecase];
4505 pcm_params_free(*pparams); /* can accept null input */
4506 *pparams = NULL;
4507
4508 /* find the device ID for the use case (signed, for error) */
4509 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4510 if (device_id < 0)
4511 continue;
4512
4513 /* prepare structures for device probing */
4514 memset(&uc_info, 0, sizeof(uc_info));
4515 uc_info.id = audio_usecase;
4516 uc_info.type = usecase_type;
4517 if (dir) {
4518 adev->active_input = &in;
4519 memset(&in, 0, sizeof(in));
4520 in.device = audio_device;
4521 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4522 uc_info.stream.in = &in;
4523 } else {
4524 adev->active_input = NULL;
4525 }
4526 memset(&out, 0, sizeof(out));
4527 out.devices = audio_device; /* only field needed in select_devices */
4528 uc_info.stream.out = &out;
4529 uc_info.devices = audio_device;
4530 uc_info.in_snd_device = SND_DEVICE_NONE;
4531 uc_info.out_snd_device = SND_DEVICE_NONE;
4532 list_add_tail(&adev->usecase_list, &uc_info.list);
4533
4534 /* select device - similar to start_(in/out)put_stream() */
4535 retval = select_devices(adev, audio_usecase);
4536 if (retval >= 0) {
4537 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4538#if LOG_NDEBUG == 0
4539 if (*pparams) {
4540 ALOGV("%s: (%s) card %d device %d", __func__,
4541 dir ? "input" : "output", card_id, device_id);
4542 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004543 } else {
4544 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4545 }
4546#endif
4547 }
4548
4549 /* deselect device - similar to stop_(in/out)put_stream() */
4550 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004551 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004552 /* 2. Disable the rx device */
4553 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004554 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004555 list_remove(&uc_info.list);
4556 }
4557 }
4558 adev->active_input = NULL; /* restore adev state */
4559 return 0;
4560}
4561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562static int adev_close(hw_device_t *device)
4563{
Andy Hung31aca912014-03-20 17:14:59 -07004564 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004566
4567 if (!adev)
4568 return 0;
4569
4570 pthread_mutex_lock(&adev_init_lock);
4571
4572 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004573 audio_extn_snd_mon_unregister_listener(adev);
4574 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004575 audio_route_free(adev->audio_route);
4576 free(adev->snd_dev_ref_cnt);
4577 platform_deinit(adev->platform);
4578 audio_extn_extspk_deinit(adev->extspk);
4579 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004580 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004581 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4582 pcm_params_free(adev->use_case_table[i]);
4583 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004584 if (adev->adm_deinit)
4585 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004586 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004587 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004588
4589 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004590
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591 return 0;
4592}
4593
Glenn Kasten4f993392014-05-14 07:30:48 -07004594/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4595 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4596 * just that it _might_ work.
4597 */
4598static int period_size_is_plausible_for_low_latency(int period_size)
4599{
4600 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004601 case 48:
4602 case 96:
4603 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004604 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004605 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004606 case 240:
4607 case 320:
4608 case 480:
4609 return 1;
4610 default:
4611 return 0;
4612 }
4613}
4614
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004615static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4616{
4617 int card;
4618 card_status_t status;
4619
4620 if (!parms)
4621 return;
4622
4623 if (parse_snd_card_status(parms, &card, &status) < 0)
4624 return;
4625
4626 pthread_mutex_lock(&adev->lock);
4627 bool valid_cb = (card == adev->snd_card);
4628 if (valid_cb) {
4629 if (adev->card_status != status) {
4630 adev->card_status = status;
4631 platform_snd_card_update(adev->platform, status);
4632 }
4633 }
4634 pthread_mutex_unlock(&adev->lock);
4635 return;
4636}
4637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638static int adev_open(const hw_module_t *module, const char *name,
4639 hw_device_t **device)
4640{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004641 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642
Eric Laurent2bafff12016-03-17 12:17:23 -07004643 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004645 pthread_mutex_lock(&adev_init_lock);
4646 if (audio_device_ref_count != 0) {
4647 *device = &adev->device.common;
4648 audio_device_ref_count++;
4649 ALOGV("%s: returning existing instance of adev", __func__);
4650 ALOGV("%s: exit", __func__);
4651 pthread_mutex_unlock(&adev_init_lock);
4652 return 0;
4653 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 adev = calloc(1, sizeof(struct audio_device));
4655
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004656 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004658 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4659 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4660 adev->device.common.module = (struct hw_module_t *)module;
4661 adev->device.common.close = adev_close;
4662
4663 adev->device.init_check = adev_init_check;
4664 adev->device.set_voice_volume = adev_set_voice_volume;
4665 adev->device.set_master_volume = adev_set_master_volume;
4666 adev->device.get_master_volume = adev_get_master_volume;
4667 adev->device.set_master_mute = adev_set_master_mute;
4668 adev->device.get_master_mute = adev_get_master_mute;
4669 adev->device.set_mode = adev_set_mode;
4670 adev->device.set_mic_mute = adev_set_mic_mute;
4671 adev->device.get_mic_mute = adev_get_mic_mute;
4672 adev->device.set_parameters = adev_set_parameters;
4673 adev->device.get_parameters = adev_get_parameters;
4674 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4675 adev->device.open_output_stream = adev_open_output_stream;
4676 adev->device.close_output_stream = adev_close_output_stream;
4677 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004679 adev->device.close_input_stream = adev_close_input_stream;
4680 adev->device.dump = adev_dump;
4681
4682 /* Set the default route before the PCM stream is opened */
4683 pthread_mutex_lock(&adev->lock);
4684 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004685 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004686 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004688 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004689 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004690 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004691 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004692 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693 pthread_mutex_unlock(&adev->lock);
4694
4695 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004696 adev->platform = platform_init(adev);
4697 if (!adev->platform) {
4698 free(adev->snd_dev_ref_cnt);
4699 free(adev);
4700 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4701 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004702 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004703 return -EINVAL;
4704 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004705 adev->extspk = audio_extn_extspk_init(adev);
4706
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004707 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4708 if (adev->visualizer_lib == NULL) {
4709 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4710 } else {
4711 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4712 adev->visualizer_start_output =
4713 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4714 "visualizer_hal_start_output");
4715 adev->visualizer_stop_output =
4716 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4717 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004718 }
4719
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004720 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4721 if (adev->offload_effects_lib == NULL) {
4722 ALOGW("%s: DLOPEN failed for %s", __func__,
4723 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4724 } else {
4725 ALOGV("%s: DLOPEN successful for %s", __func__,
4726 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4727 adev->offload_effects_start_output =
4728 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4729 "offload_effects_bundle_hal_start_output");
4730 adev->offload_effects_stop_output =
4731 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4732 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004733 }
4734
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004735 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4736 if (adev->adm_lib == NULL) {
4737 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4738 } else {
4739 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4740 adev->adm_init = (adm_init_t)
4741 dlsym(adev->adm_lib, "adm_init");
4742 adev->adm_deinit = (adm_deinit_t)
4743 dlsym(adev->adm_lib, "adm_deinit");
4744 adev->adm_register_input_stream = (adm_register_input_stream_t)
4745 dlsym(adev->adm_lib, "adm_register_input_stream");
4746 adev->adm_register_output_stream = (adm_register_output_stream_t)
4747 dlsym(adev->adm_lib, "adm_register_output_stream");
4748 adev->adm_deregister_stream = (adm_deregister_stream_t)
4749 dlsym(adev->adm_lib, "adm_deregister_stream");
4750 adev->adm_request_focus = (adm_request_focus_t)
4751 dlsym(adev->adm_lib, "adm_request_focus");
4752 adev->adm_abandon_focus = (adm_abandon_focus_t)
4753 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004754 adev->adm_set_config = (adm_set_config_t)
4755 dlsym(adev->adm_lib, "adm_set_config");
4756 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4757 dlsym(adev->adm_lib, "adm_request_focus_v2");
4758 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4759 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4760 adev->adm_on_routing_change = (adm_on_routing_change_t)
4761 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004762 }
4763
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004764 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004765 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004768
Andy Hung31aca912014-03-20 17:14:59 -07004769 if (k_enable_extended_precision)
4770 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771
Glenn Kasten4f993392014-05-14 07:30:48 -07004772 char value[PROPERTY_VALUE_MAX];
4773 int trial;
4774 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4775 trial = atoi(value);
4776 if (period_size_is_plausible_for_low_latency(trial)) {
4777 pcm_config_low_latency.period_size = trial;
4778 pcm_config_low_latency.start_threshold = trial / 4;
4779 pcm_config_low_latency.avail_min = trial / 4;
4780 configured_low_latency_capture_period_size = trial;
4781 }
4782 }
4783 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4784 trial = atoi(value);
4785 if (period_size_is_plausible_for_low_latency(trial)) {
4786 configured_low_latency_capture_period_size = trial;
4787 }
4788 }
4789
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004790 // commented as full set of app type cfg is sent from platform
4791 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004792 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004793
4794 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4795 af_period_multiplier = atoi(value);
4796 if (af_period_multiplier < 0) {
4797 af_period_multiplier = 2;
4798 } else if (af_period_multiplier > 4) {
4799 af_period_multiplier = 4;
4800 }
4801 ALOGV("new period_multiplier = %d", af_period_multiplier);
4802 }
4803
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004804 audio_extn_tfa_98xx_init(adev);
4805
vivek mehta1a9b7c02015-06-25 11:49:38 -07004806 pthread_mutex_unlock(&adev_init_lock);
4807
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004808 if (adev->adm_init)
4809 adev->adm_data = adev->adm_init();
4810
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004811 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004812 audio_extn_snd_mon_init();
4813 pthread_mutex_lock(&adev->lock);
4814 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4815 adev->card_status = CARD_STATUS_ONLINE;
4816 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004817 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004818
Eric Laurent2bafff12016-03-17 12:17:23 -07004819 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004820 return 0;
4821}
4822
4823static struct hw_module_methods_t hal_module_methods = {
4824 .open = adev_open,
4825};
4826
4827struct audio_module HAL_MODULE_INFO_SYM = {
4828 .common = {
4829 .tag = HARDWARE_MODULE_TAG,
4830 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4831 .hal_api_version = HARDWARE_HAL_API_VERSION,
4832 .id = AUDIO_HARDWARE_MODULE_ID,
4833 .name = "QCOM Audio HAL",
4834 .author = "Code Aurora Forum",
4835 .methods = &hal_module_methods,
4836 },
4837};