blob: cb54e802b6b5648ad04ae9f09a9a9122f7cde7dc [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
2521 const int frame_size = audio_stream_out_frame_size(stream);
2522
Eric Laurent0e46adf2016-12-16 12:49:24 -08002523 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2524 error_code = ERROR_CODE_WRITE;
2525 goto exit;
2526 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002528 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002529 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002530 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002531 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002532 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002534 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 goto exit;
2536 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002537
2538 if (last_known_cal_step != -1) {
2539 ALOGD("%s: retry previous failed cal level set", __func__);
2540 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002544 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002545 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002546 if (out->send_new_metadata) {
2547 ALOGVV("send new gapless metadata");
2548 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2549 out->send_new_metadata = 0;
2550 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002551 unsigned int avail;
2552 struct timespec tstamp;
2553 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2554 /* Do not limit write size if the available frames count is unknown */
2555 if (ret != 0) {
2556 avail = bytes;
2557 }
2558 if (avail == 0) {
2559 ret = 0;
2560 } else {
2561 if (avail > bytes) {
2562 avail = bytes;
2563 }
2564 ret = compress_write(out->compr, buffer, avail);
2565 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2566 __func__, avail, ret);
2567 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002568
Eric Laurent6e895242013-09-05 16:10:57 -07002569 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002570 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2571 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002572 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002573 compress_start(out->compr);
2574 out->playback_started = 1;
2575 out->offload_state = OFFLOAD_STATE_PLAYING;
2576 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002577 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002578 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002579 } else {
2580 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002581 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002583 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002584 return ret;
2585 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002586 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002587 if (out->pcm) {
2588 if (out->muted)
2589 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002590
Eric Laurent0e46adf2016-12-16 12:49:24 -08002591 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002592
Haynes Mathew George03c40102016-01-29 17:57:48 -08002593 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2594 out->config.rate;
2595 request_out_focus(out, ns);
2596
2597 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2598 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002599 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002600 else
2601 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002602
Haynes Mathew George03c40102016-01-29 17:57:48 -08002603 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002604 } else {
2605 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002606 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 }
2608
2609exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002610 // For PCM we always consume the buffer and return #bytes regardless of ret.
2611 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2612 out->written += bytes / (out->config.channels * sizeof(short));
2613 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002614 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002615
2616 // only get time if needed for logging, as it is a system call on 32 bit devices.
2617 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2618 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2619 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002620
Andy Hung7401c7c2016-09-21 12:41:21 -07002621 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002622 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002623 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2624 ALOGE_IF(out->pcm != NULL,
2625 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002626 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002627 out_get_sample_rate(&out->stream.common);
2628 // 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)
2640 power_log_log(out->power_log, buffer, bytes / frame_size, 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);
3201
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003202 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003203 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003204 /* Read from sound trigger HAL */
3205 audio_extn_sound_trigger_read(in, buffer, bytes);
3206 pthread_mutex_unlock(&in->lock);
3207 return bytes;
3208 }
3209
Eric Laurent0e46adf2016-12-16 12:49:24 -08003210 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3211 ret = -ENOSYS;
3212 goto exit;
3213 }
3214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003216 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003218 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220 goto exit;
3221 }
3222 in->standby = 0;
3223 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224
Haynes Mathew George03c40102016-01-29 17:57:48 -08003225 //what's the duration requested by the client?
3226 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3227 in->config.rate;
3228 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003229
Haynes Mathew George03c40102016-01-29 17:57:48 -08003230 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003231 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003232 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003233 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003234 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003235 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003236 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003237 if (ret < 0) {
3238 ALOGE("Failed to read w/err %s", strerror(errno));
3239 ret = -errno;
3240 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003241 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3242 if (bytes % 4 == 0) {
3243 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3244 int_buf_stream = buffer;
3245 for (size_t itt=0; itt < bytes/4 ; itt++) {
3246 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003247 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003248 } else {
3249 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3250 ret = -EINVAL;
3251 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003252 }
3253 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003254 }
3255
Haynes Mathew George03c40102016-01-29 17:57:48 -08003256 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258 /*
3259 * Instead of writing zeroes here, we could trust the hardware
3260 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003261 * 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 -08003262 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003263 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003264 memset(buffer, 0, bytes);
3265
3266exit:
3267 pthread_mutex_unlock(&in->lock);
3268
3269 if (ret != 0) {
3270 in_standby(&in->stream.common);
3271 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07003272 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003274 memset(buffer, 0, bytes); // clear return data
3275 }
3276 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08003277 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278 }
3279 return bytes;
3280}
3281
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003282static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283{
3284 return 0;
3285}
3286
Andy Hung6ebe5962016-01-15 17:46:57 -08003287static int in_get_capture_position(const struct audio_stream_in *stream,
3288 int64_t *frames, int64_t *time)
3289{
3290 if (stream == NULL || frames == NULL || time == NULL) {
3291 return -EINVAL;
3292 }
3293 struct stream_in *in = (struct stream_in *)stream;
3294 int ret = -ENOSYS;
3295
3296 lock_input_stream(in);
3297 if (in->pcm) {
3298 struct timespec timestamp;
3299 unsigned int avail;
3300 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3301 *frames = in->frames_read + avail;
3302 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3303 ret = 0;
3304 }
3305 }
3306 pthread_mutex_unlock(&in->lock);
3307 return ret;
3308}
3309
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003310static int add_remove_audio_effect(const struct audio_stream *stream,
3311 effect_handle_t effect,
3312 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003314 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003315 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003316 int status = 0;
3317 effect_descriptor_t desc;
3318
3319 status = (*effect)->get_descriptor(effect, &desc);
3320 if (status != 0)
3321 return status;
3322
Eric Laurenta1478072015-09-21 17:21:52 -07003323 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003324 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003325 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003326 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003327 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003328 in->enable_aec != enable &&
3329 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3330 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003331 if (!enable)
3332 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003333 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3334 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3335 adev->enable_voicerx = enable;
3336 struct audio_usecase *usecase;
3337 struct listnode *node;
3338 list_for_each(node, &adev->usecase_list) {
3339 usecase = node_to_item(node, struct audio_usecase, list);
3340 if (usecase->type == PCM_PLAYBACK) {
3341 select_devices(adev, usecase->id);
3342 break;
3343 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003344 }
3345 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003346 if (!in->standby)
3347 select_devices(in->dev, in->usecase);
3348 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003349 if (in->enable_ns != enable &&
3350 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3351 in->enable_ns = enable;
3352 if (!in->standby)
3353 select_devices(in->dev, in->usecase);
3354 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003355 pthread_mutex_unlock(&in->dev->lock);
3356 pthread_mutex_unlock(&in->lock);
3357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003358 return 0;
3359}
3360
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003361static int in_add_audio_effect(const struct audio_stream *stream,
3362 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363{
Eric Laurent994a6932013-07-17 11:51:42 -07003364 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003365 return add_remove_audio_effect(stream, effect, true);
3366}
3367
3368static int in_remove_audio_effect(const struct audio_stream *stream,
3369 effect_handle_t effect)
3370{
Eric Laurent994a6932013-07-17 11:51:42 -07003371 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003372 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003373}
3374
Eric Laurent0e46adf2016-12-16 12:49:24 -08003375static int in_stop(const struct audio_stream_in* stream)
3376{
3377 struct stream_in *in = (struct stream_in *)stream;
3378 struct audio_device *adev = in->dev;
3379
3380 int ret = -ENOSYS;
3381 ALOGV("%s", __func__);
3382 pthread_mutex_lock(&adev->lock);
3383 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3384 in->capture_started && in->pcm != NULL) {
3385 pcm_stop(in->pcm);
3386 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003387 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003388 }
3389 pthread_mutex_unlock(&adev->lock);
3390 return ret;
3391}
3392
3393static int in_start(const struct audio_stream_in* stream)
3394{
3395 struct stream_in *in = (struct stream_in *)stream;
3396 struct audio_device *adev = in->dev;
3397 int ret = -ENOSYS;
3398
3399 ALOGV("%s in %p", __func__, in);
3400 pthread_mutex_lock(&adev->lock);
3401 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3402 !in->capture_started && in->pcm != NULL) {
3403 if (!in->capture_started) {
3404 ret = start_input_stream(in);
3405 if (ret == 0) {
3406 in->capture_started = true;
3407 }
3408 }
3409 }
3410 pthread_mutex_unlock(&adev->lock);
3411 return ret;
3412}
3413
3414static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3415 int32_t min_size_frames,
3416 struct audio_mmap_buffer_info *info)
3417{
3418 struct stream_in *in = (struct stream_in *)stream;
3419 struct audio_device *adev = in->dev;
3420 int ret = 0;
3421 unsigned int offset1;
3422 unsigned int frames1;
3423 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003424 uint32_t mmap_size;
3425 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003426
3427 pthread_mutex_lock(&adev->lock);
3428 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003429
Eric Laurent0e46adf2016-12-16 12:49:24 -08003430 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003431 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003432 ret = -EINVAL;
3433 goto exit;
3434 }
3435 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003436 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003437 ALOGV("%s in %p", __func__, in);
3438 ret = -ENOSYS;
3439 goto exit;
3440 }
3441 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3442 if (in->pcm_device_id < 0) {
3443 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3444 __func__, in->pcm_device_id, in->usecase);
3445 ret = -EINVAL;
3446 goto exit;
3447 }
Phil Burkbc991042017-02-24 08:06:44 -08003448
3449 adjust_mmap_period_count(&in->config, min_size_frames);
3450
Eric Laurent0e46adf2016-12-16 12:49:24 -08003451 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3452 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3453 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3454 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3455 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3456 step = "open";
3457 ret = -ENODEV;
3458 goto exit;
3459 }
3460
3461 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3462 if (ret < 0) {
3463 step = "begin";
3464 goto exit;
3465 }
3466 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003467 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003468 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003469 ret = platform_get_mmap_data_fd(adev->platform,
3470 in->pcm_device_id, 1 /*capture*/,
3471 &info->shared_memory_fd,
3472 &mmap_size);
3473 if (ret < 0) {
3474 // Fall back to non exclusive mode
3475 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3476 } else {
3477 if (mmap_size < buffer_size) {
3478 step = "mmap";
3479 goto exit;
3480 }
3481 // FIXME: indicate exclusive mode support by returning a negative buffer size
3482 info->buffer_size_frames *= -1;
3483 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003484
Haynes Mathew George96483a22017-03-28 14:52:47 -07003485 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003486
3487 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3488 if (ret < 0) {
3489 step = "commit";
3490 goto exit;
3491 }
3492
Phil Burkbc991042017-02-24 08:06:44 -08003493 in->standby = false;
3494 ret = 0;
3495
Eric Laurent0e46adf2016-12-16 12:49:24 -08003496 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3497 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003498
3499exit:
3500 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003501 if (in->pcm == NULL) {
3502 ALOGE("%s: %s - %d", __func__, step, ret);
3503 } else {
3504 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003505 pcm_close(in->pcm);
3506 in->pcm = NULL;
3507 }
3508 }
3509 pthread_mutex_unlock(&adev->lock);
3510 return ret;
3511}
3512
3513static int in_get_mmap_position(const struct audio_stream_in *stream,
3514 struct audio_mmap_position *position)
3515{
3516 struct stream_in *in = (struct stream_in *)stream;
3517 ALOGVV("%s", __func__);
3518 if (position == NULL) {
3519 return -EINVAL;
3520 }
3521 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3522 return -ENOSYS;
3523 }
3524 if (in->pcm == NULL) {
3525 return -ENOSYS;
3526 }
3527 struct timespec ts = { 0, 0 };
3528 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3529 if (ret < 0) {
3530 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3531 return ret;
3532 }
Andy Hungfc044e12017-03-20 09:24:22 -07003533 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003534 return 0;
3535}
3536
3537
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538static int adev_open_output_stream(struct audio_hw_device *dev,
3539 audio_io_handle_t handle,
3540 audio_devices_t devices,
3541 audio_output_flags_t flags,
3542 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003543 struct audio_stream_out **stream_out,
3544 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545{
3546 struct audio_device *adev = (struct audio_device *)dev;
3547 struct stream_out *out;
3548 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003549 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3550 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3551 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3552 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553
Eric Laurent994a6932013-07-17 11:51:42 -07003554 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555 __func__, config->sample_rate, config->channel_mask, devices, flags);
3556 *stream_out = NULL;
3557 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3558
3559 if (devices == AUDIO_DEVICE_NONE)
3560 devices = AUDIO_DEVICE_OUT_SPEAKER;
3561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 out->flags = flags;
3563 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003564 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003565 out->format = config->format;
3566 out->sample_rate = config->sample_rate;
3567 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3568 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003569 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570
3571 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003572 if (audio_is_linear_pcm(out->format) &&
3573 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003574 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003575 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003576 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003577 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003578 if (config->sample_rate == 0)
3579 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3580 if (config->channel_mask == 0)
3581 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3582 if (config->format == AUDIO_FORMAT_DEFAULT)
3583 config->format = AUDIO_FORMAT_PCM_16_BIT;
3584 } else if (is_usb_dev) {
3585 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3586 &config->format,
3587 &out->supported_formats[0],
3588 MAX_SUPPORTED_FORMATS,
3589 &config->channel_mask,
3590 &out->supported_channel_masks[0],
3591 MAX_SUPPORTED_CHANNEL_MASKS,
3592 &config->sample_rate,
3593 &out->supported_sample_rates[0],
3594 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003595 ALOGV("plugged dev USB ret %d", ret);
3596 } else {
3597 ret = -1;
3598 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003599 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003600 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003601 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003602
Haynes Mathew George569b7482017-05-08 14:44:27 -07003603 out->channel_mask = config->channel_mask;
3604 out->sample_rate = config->sample_rate;
3605 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003606 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3607 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003608 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003610 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003612 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003613 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003614 pthread_mutex_lock(&adev->lock);
3615 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3616 pthread_mutex_unlock(&adev->lock);
3617
3618 // reject offload during card offline to allow
3619 // fallback to s/w paths
3620 if (offline) {
3621 ret = -ENODEV;
3622 goto error_open;
3623 }
3624
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003625 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3626 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3627 ALOGE("%s: Unsupported Offload information", __func__);
3628 ret = -EINVAL;
3629 goto error_open;
3630 }
3631 if (!is_supported_format(config->offload_info.format)) {
3632 ALOGE("%s: Unsupported audio format", __func__);
3633 ret = -EINVAL;
3634 goto error_open;
3635 }
3636
3637 out->compr_config.codec = (struct snd_codec *)
3638 calloc(1, sizeof(struct snd_codec));
3639
3640 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3641 if (config->offload_info.channel_mask)
3642 out->channel_mask = config->offload_info.channel_mask;
3643 else if (config->channel_mask)
3644 out->channel_mask = config->channel_mask;
3645 out->format = config->offload_info.format;
3646 out->sample_rate = config->offload_info.sample_rate;
3647
3648 out->stream.set_callback = out_set_callback;
3649 out->stream.pause = out_pause;
3650 out->stream.resume = out_resume;
3651 out->stream.drain = out_drain;
3652 out->stream.flush = out_flush;
3653
3654 out->compr_config.codec->id =
3655 get_snd_codec_id(config->offload_info.format);
3656 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3657 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003658 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003659 out->compr_config.codec->bit_rate =
3660 config->offload_info.bit_rate;
3661 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003662 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003663 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3664
3665 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3666 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003667
3668 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003669 create_offload_callback_thread(out);
3670 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3671 __func__, config->offload_info.version,
3672 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003673 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003674 switch (config->sample_rate) {
3675 case 8000:
3676 case 16000:
3677 case 48000:
3678 out->sample_rate = config->sample_rate;
3679 break;
3680 default:
3681 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003682 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003683 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003684 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3685 out->config = pcm_config_afe_proxy_playback;
3686 adev->voice_tx_output = out;
vivek mehtaa68fea62017-06-08 19:04:02 -07003687 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3688 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3689 AUDIO_OUTPUT_FLAG_VOIP_RX))) {
3690 uint32_t buffer_size, frame_size;
3691 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3692 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3693 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3694 out->config = pcm_config_voip;
3695 out->config.format = pcm_format_from_audio_format(config->format);
3696 out->config.rate = config->sample_rate;
3697 out->config.channels =
3698 audio_channel_count_from_out_mask(config->channel_mask);
3699 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3700 config->sample_rate,
3701 config->format,
3702 out->config.channels,
3703 false /*is_low_latency*/);
3704 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3705 out->config.period_size = buffer_size / frame_size;
3706 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3707 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003709 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3710 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3711 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003712 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3713 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3714 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003715 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3716 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003717 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003718 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003719 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3720 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3721 out->config = pcm_config_mmap_playback;
3722 out->stream.start = out_start;
3723 out->stream.stop = out_stop;
3724 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3725 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003726 } else {
3727 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3728 out->config = pcm_config_low_latency;
3729 }
3730 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003731 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003732 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003733 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003734 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003735
3736 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3737 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3738 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3739 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3740 __func__, config->sample_rate, config->format, config->channel_mask);
3741 config->sample_rate = out->sample_rate;
3742 config->format = out->format;
3743 config->channel_mask = out->channel_mask;
3744 ret = -EINVAL;
3745 goto error_open;
3746 }
3747
Andy Hung6fcba9c2014-03-18 11:53:32 -07003748 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3749 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003751 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003752 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003753 adev->primary_output = out;
3754 else {
3755 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003756 ret = -EEXIST;
3757 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003758 }
3759 }
3760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003761 /* Check if this usecase is already existing */
3762 pthread_mutex_lock(&adev->lock);
3763 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3764 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003765 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003766 ret = -EEXIST;
3767 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 }
3769 pthread_mutex_unlock(&adev->lock);
3770
3771 out->stream.common.get_sample_rate = out_get_sample_rate;
3772 out->stream.common.set_sample_rate = out_set_sample_rate;
3773 out->stream.common.get_buffer_size = out_get_buffer_size;
3774 out->stream.common.get_channels = out_get_channels;
3775 out->stream.common.get_format = out_get_format;
3776 out->stream.common.set_format = out_set_format;
3777 out->stream.common.standby = out_standby;
3778 out->stream.common.dump = out_dump;
3779 out->stream.common.set_parameters = out_set_parameters;
3780 out->stream.common.get_parameters = out_get_parameters;
3781 out->stream.common.add_audio_effect = out_add_audio_effect;
3782 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3783 out->stream.get_latency = out_get_latency;
3784 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003785#ifdef NO_AUDIO_OUT
3786 out->stream.write = out_write_for_no_output;
3787#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003788 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003789#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790 out->stream.get_render_position = out_get_render_position;
3791 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003792 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793
Eric Laurent0e46adf2016-12-16 12:49:24 -08003794 if (out->realtime)
3795 out->af_period_multiplier = af_period_multiplier;
3796 else
3797 out->af_period_multiplier = 1;
3798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003800 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003801 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003803 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003804 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003805 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3806
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807 config->format = out->stream.common.get_format(&out->stream.common);
3808 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3809 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3810
Andy Hunga452b0a2017-03-15 14:51:15 -07003811 out->error_log = error_log_create(
3812 ERROR_LOG_ENTRIES,
3813 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3814
Andy Hungfc044e12017-03-20 09:24:22 -07003815 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003816 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003817 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003818 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3819 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3820
3821 out->power_log = power_log_create(
3822 config->sample_rate,
3823 audio_channel_count_from_out_mask(config->channel_mask),
3824 config->format,
3825 POWER_LOG_ENTRIES,
3826 POWER_LOG_FRAMES_PER_ENTRY);
3827 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003828
3829 /*
3830 By locking output stream before registering, we allow the callback
3831 to update stream's state only after stream's initial state is set to
3832 adev state.
3833 */
3834 lock_output_stream(out);
3835 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3836 pthread_mutex_lock(&adev->lock);
3837 out->card_status = adev->card_status;
3838 pthread_mutex_unlock(&adev->lock);
3839 pthread_mutex_unlock(&out->lock);
3840
vivek mehta4a824772017-06-08 19:05:49 -07003841 stream_app_type_cfg_init(&out->app_type_cfg);
3842
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003844
Eric Laurent994a6932013-07-17 11:51:42 -07003845 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003847
3848error_open:
3849 free(out);
3850 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003851 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003852 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853}
3854
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003855static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856 struct audio_stream_out *stream)
3857{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003858 struct stream_out *out = (struct stream_out *)stream;
3859 struct audio_device *adev = out->dev;
3860
Eric Laurent994a6932013-07-17 11:51:42 -07003861 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003862
3863 // must deregister from sndmonitor first to prevent races
3864 // between the callback and close_stream
3865 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003866 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003867 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3868 destroy_offload_callback_thread(out);
3869
3870 if (out->compr_config.codec != NULL)
3871 free(out->compr_config.codec);
3872 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003873
3874 if (adev->voice_tx_output == out)
3875 adev->voice_tx_output = NULL;
3876
Andy Hungfc044e12017-03-20 09:24:22 -07003877 power_log_destroy(out->power_log);
3878 out->power_log = NULL;
3879
Andy Hunga452b0a2017-03-15 14:51:15 -07003880 error_log_destroy(out->error_log);
3881 out->error_log = NULL;
3882
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003883 pthread_cond_destroy(&out->cond);
3884 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003886 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887}
3888
3889static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3890{
3891 struct audio_device *adev = (struct audio_device *)dev;
3892 struct str_parms *parms;
3893 char *str;
3894 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003895 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003897 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898
Joe Onorato188b6222016-03-01 11:02:27 -08003899 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003900
3901 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902
3903 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003904 status = voice_set_parameters(adev, parms);
3905 if (status != 0) {
3906 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003907 }
3908
3909 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3910 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003911 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003912 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3913 adev->bluetooth_nrec = true;
3914 else
3915 adev->bluetooth_nrec = false;
3916 }
3917
3918 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3919 if (ret >= 0) {
3920 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3921 adev->screen_off = false;
3922 else
3923 adev->screen_off = true;
3924 }
3925
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003926 ret = str_parms_get_int(parms, "rotation", &val);
3927 if (ret >= 0) {
3928 bool reverse_speakers = false;
3929 switch(val) {
3930 // FIXME: note that the code below assumes that the speakers are in the correct placement
3931 // relative to the user when the device is rotated 90deg from its default rotation. This
3932 // assumption is device-specific, not platform-specific like this code.
3933 case 270:
3934 reverse_speakers = true;
3935 break;
3936 case 0:
3937 case 90:
3938 case 180:
3939 break;
3940 default:
3941 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003942 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003943 }
Eric Laurent03f09432014-03-25 18:09:11 -07003944 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07003945 // check and set swap
3946 // - check if orientation changed and speaker active
3947 // - set rotation and cache the rotation value
3948 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003949 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003950 }
3951
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003952 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3953 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003954 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003955 }
3956
David Linee3fe402017-03-13 10:00:42 -07003957 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3958 if (ret >= 0) {
3959 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003960 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003961 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3962 if (ret >= 0) {
3963 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003964 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003965 }
Eric Laurent99dab492017-06-17 15:19:08 -07003966 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003967 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3968 if (ret >= 0) {
3969 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003970 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003971 }
3972 }
3973 }
3974
3975 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3976 if (ret >= 0) {
3977 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003978 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003979 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3980 if (ret >= 0) {
3981 const int card = atoi(value);
3982
Eric Laurent99dab492017-06-17 15:19:08 -07003983 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003984 }
Eric Laurent99dab492017-06-17 15:19:08 -07003985 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003986 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3987 if (ret >= 0) {
3988 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003989 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003990 }
3991 }
3992 }
3993
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003994 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003995done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003996 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003997 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003998 ALOGV("%s: exit with code(%d)", __func__, status);
3999 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000}
4001
4002static char* adev_get_parameters(const struct audio_hw_device *dev,
4003 const char *keys)
4004{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004005 struct audio_device *adev = (struct audio_device *)dev;
4006 struct str_parms *reply = str_parms_create();
4007 struct str_parms *query = str_parms_create_str(keys);
4008 char *str;
4009
4010 pthread_mutex_lock(&adev->lock);
4011
4012 voice_get_parameters(adev, query, reply);
4013 str = str_parms_to_str(reply);
4014 str_parms_destroy(query);
4015 str_parms_destroy(reply);
4016
4017 pthread_mutex_unlock(&adev->lock);
4018 ALOGV("%s: exit: returns - %s", __func__, str);
4019 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004020}
4021
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004022static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004023{
4024 return 0;
4025}
4026
Haynes Mathew George5191a852013-09-11 14:19:36 -07004027static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4028{
4029 int ret;
4030 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004031
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004032 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4033
Haynes Mathew George5191a852013-09-11 14:19:36 -07004034 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004035 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004036 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004037
Haynes Mathew George5191a852013-09-11 14:19:36 -07004038 return ret;
4039}
4040
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004041static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004042{
4043 return -ENOSYS;
4044}
4045
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004046static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4047 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004048{
4049 return -ENOSYS;
4050}
4051
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004052static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053{
4054 return -ENOSYS;
4055}
4056
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004057static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058{
4059 return -ENOSYS;
4060}
4061
4062static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4063{
4064 struct audio_device *adev = (struct audio_device *)dev;
4065
4066 pthread_mutex_lock(&adev->lock);
4067 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004068 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004070 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4071 voice_is_in_call(adev)) {
4072 voice_stop_call(adev);
4073 adev->current_call_output = NULL;
4074 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004075 }
4076 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004077
4078 audio_extn_extspk_set_mode(adev->extspk, mode);
4079
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004080 return 0;
4081}
4082
4083static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4084{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004085 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004086 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087
Eric Laurent2bafff12016-03-17 12:17:23 -07004088 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004089 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004090 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4091 ret = audio_extn_hfp_set_mic_mute(adev, state);
4092 } else {
4093 ret = voice_set_mic_mute(adev, state);
4094 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004095 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004096 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004097
4098 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099}
4100
4101static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4102{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004103 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104 return 0;
4105}
4106
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004107static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004108 const struct audio_config *config)
4109{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004110 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111
Eric Laurent74b55762017-07-09 17:04:53 -07004112 /* Don't know if USB HIFI in this context so use true to be conservative */
4113 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4114 true /*is_usb_hifi */) != 0)
4115 return 0;
4116
vivek mehtaa68fea62017-06-08 19:04:02 -07004117 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4118 config->sample_rate, config->format,
4119 channel_count,
4120 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121}
4122
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004123static bool adev_input_allow_hifi_record(struct audio_device *adev,
4124 audio_devices_t devices,
4125 audio_input_flags_t flags,
4126 audio_source_t source) {
4127 const bool allowed = true;
4128
4129 if (!audio_is_usb_in_device(devices))
4130 return !allowed;
4131
4132 switch (flags) {
4133 case AUDIO_INPUT_FLAG_NONE:
4134 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4135 break;
4136 default:
4137 return !allowed;
4138 }
4139
4140 switch (source) {
4141 case AUDIO_SOURCE_DEFAULT:
4142 case AUDIO_SOURCE_MIC:
4143 case AUDIO_SOURCE_UNPROCESSED:
4144 break;
4145 default:
4146 return !allowed;
4147 }
4148
4149 switch (adev->mode) {
4150 case 0:
4151 break;
4152 default:
4153 return !allowed;
4154 }
4155
4156 return allowed;
4157}
4158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004160 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161 audio_devices_t devices,
4162 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004163 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004164 audio_input_flags_t flags,
4165 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004166 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004167{
4168 struct audio_device *adev = (struct audio_device *)dev;
4169 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004170 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004171 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004172 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004173 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004174 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4175 devices,
4176 flags,
4177 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004178 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004180
Eric Laurent74b55762017-07-09 17:04:53 -07004181 if (!(is_usb_dev && may_use_hifi_record)) {
4182 if (config->sample_rate == 0)
4183 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4184 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4185 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4186 if (config->format == AUDIO_FORMAT_DEFAULT)
4187 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004188
Eric Laurent74b55762017-07-09 17:04:53 -07004189 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4190
4191 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4192 return -EINVAL;
4193 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004195 if (audio_extn_tfa_98xx_is_supported() &&
4196 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004197 return -EINVAL;
4198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004199 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4200
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004201 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004202 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204 in->stream.common.get_sample_rate = in_get_sample_rate;
4205 in->stream.common.set_sample_rate = in_set_sample_rate;
4206 in->stream.common.get_buffer_size = in_get_buffer_size;
4207 in->stream.common.get_channels = in_get_channels;
4208 in->stream.common.get_format = in_get_format;
4209 in->stream.common.set_format = in_set_format;
4210 in->stream.common.standby = in_standby;
4211 in->stream.common.dump = in_dump;
4212 in->stream.common.set_parameters = in_set_parameters;
4213 in->stream.common.get_parameters = in_get_parameters;
4214 in->stream.common.add_audio_effect = in_add_audio_effect;
4215 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4216 in->stream.set_gain = in_set_gain;
4217 in->stream.read = in_read;
4218 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004219 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220
4221 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004222 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004224 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004225 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004226 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227
Haynes Mathew George569b7482017-05-08 14:44:27 -07004228 if (is_usb_dev && may_use_hifi_record) {
4229 /* HiFi record selects an appropriate format, channel, rate combo
4230 depending on sink capabilities*/
4231 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4232 &config->format,
4233 &in->supported_formats[0],
4234 MAX_SUPPORTED_FORMATS,
4235 &config->channel_mask,
4236 &in->supported_channel_masks[0],
4237 MAX_SUPPORTED_CHANNEL_MASKS,
4238 &config->sample_rate,
4239 &in->supported_sample_rates[0],
4240 MAX_SUPPORTED_SAMPLE_RATES);
4241 if (ret != 0) {
4242 ret = -EINVAL;
4243 goto err_open;
4244 }
Eric Laurent74b55762017-07-09 17:04:53 -07004245 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004246 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004247 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004248 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4249 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4250 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4251 bool ret_error = false;
4252 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4253 from HAL is 8_24
4254 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4255 8_24 return error indicating supported format is 8_24
4256 *> In case of any other source requesting 24 bit or float return error
4257 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004258
vivek mehta57ff9b52016-04-28 14:13:08 -07004259 on error flinger will retry with supported format passed
4260 */
4261 if (source != AUDIO_SOURCE_UNPROCESSED) {
4262 config->format = AUDIO_FORMAT_PCM_16_BIT;
4263 ret_error = true;
4264 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4265 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4266 ret_error = true;
4267 }
4268
4269 if (ret_error) {
4270 ret = -EINVAL;
4271 goto err_open;
4272 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004273 }
4274
vivek mehta57ff9b52016-04-28 14:13:08 -07004275 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004276 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004277
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004278 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004279 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4280 if (config->sample_rate == 0)
4281 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4282 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4283 config->sample_rate != 8000) {
4284 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4285 ret = -EINVAL;
4286 goto err_open;
4287 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004288
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004289 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4290 config->format = AUDIO_FORMAT_PCM_16_BIT;
4291 ret = -EINVAL;
4292 goto err_open;
4293 }
4294
4295 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4296 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004297 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004298 } else if (is_usb_dev && may_use_hifi_record) {
4299 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4300 in->config = pcm_config_audio_capture;
4301 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004302 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4303 config->sample_rate,
4304 config->format,
4305 channel_count,
4306 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004307 in->config.period_size = buffer_size / frame_size;
4308 in->config.rate = config->sample_rate;
4309 in->af_period_multiplier = 1;
4310 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004311 } else {
4312 in->usecase = USECASE_AUDIO_RECORD;
4313 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004314 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004315 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004316#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004317 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004318#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004319 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004320 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004321 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004322 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004323 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4324 config->sample_rate,
4325 config->format,
4326 channel_count,
4327 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004328 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004329 in->config.rate = config->sample_rate;
4330 in->af_period_multiplier = 1;
4331 } else {
4332 // period size is left untouched for rt mode playback
4333 in->config = pcm_config_audio_capture_rt;
4334 in->af_period_multiplier = af_period_multiplier;
4335 }
4336 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4337 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004338 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004339 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4340 in->config = pcm_config_mmap_capture;
4341 in->stream.start = in_start;
4342 in->stream.stop = in_stop;
4343 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4344 in->stream.get_mmap_position = in_get_mmap_position;
4345 in->af_period_multiplier = 1;
4346 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004347 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
4348 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004349 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004350 (config->sample_rate == 8000 ||
4351 config->sample_rate == 16000 ||
4352 config->sample_rate == 32000 ||
4353 config->sample_rate == 48000) &&
4354 channel_count == 1) {
4355 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4356 in->config = pcm_config_audio_capture;
4357 frame_size = audio_stream_in_frame_size(&in->stream);
4358 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4359 config->sample_rate,
4360 config->format,
4361 channel_count, false /*is_low_latency*/);
4362 in->config.period_size = buffer_size / frame_size;
4363 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4364 in->config.rate = config->sample_rate;
4365 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004366 } else {
4367 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004368 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004369 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4370 config->sample_rate,
4371 config->format,
4372 channel_count,
4373 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004374 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004375 in->config.rate = config->sample_rate;
4376 in->af_period_multiplier = 1;
4377 }
4378 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4379 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004380 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004383 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004385 /* This stream could be for sound trigger lab,
4386 get sound trigger pcm if present */
4387 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004389 lock_input_stream(in);
4390 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4391 pthread_mutex_lock(&adev->lock);
4392 in->card_status = adev->card_status;
4393 pthread_mutex_unlock(&adev->lock);
4394 pthread_mutex_unlock(&in->lock);
4395
vivek mehta4a824772017-06-08 19:05:49 -07004396 stream_app_type_cfg_init(&in->app_type_cfg);
4397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004398 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004399 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400 return 0;
4401
4402err_open:
4403 free(in);
4404 *stream_in = NULL;
4405 return ret;
4406}
4407
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004408static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409 struct audio_stream_in *stream)
4410{
Eric Laurent994a6932013-07-17 11:51:42 -07004411 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004412
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004413 // must deregister from sndmonitor first to prevent races
4414 // between the callback and close_stream
4415 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004416 in_standby(&stream->common);
4417 free(stream);
4418
4419 return;
4420}
4421
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004422static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423{
4424 return 0;
4425}
4426
Andy Hung31aca912014-03-20 17:14:59 -07004427/* verifies input and output devices and their capabilities.
4428 *
4429 * This verification is required when enabling extended bit-depth or
4430 * sampling rates, as not all qcom products support it.
4431 *
4432 * Suitable for calling only on initialization such as adev_open().
4433 * It fills the audio_device use_case_table[] array.
4434 *
4435 * Has a side-effect that it needs to configure audio routing / devices
4436 * in order to power up the devices and read the device parameters.
4437 * It does not acquire any hw device lock. Should restore the devices
4438 * back to "normal state" upon completion.
4439 */
4440static int adev_verify_devices(struct audio_device *adev)
4441{
4442 /* enumeration is a bit difficult because one really wants to pull
4443 * the use_case, device id, etc from the hidden pcm_device_table[].
4444 * In this case there are the following use cases and device ids.
4445 *
4446 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4447 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004448 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004449 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4450 * [USECASE_AUDIO_RECORD] = {0, 0},
4451 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4452 * [USECASE_VOICE_CALL] = {2, 2},
4453 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004454 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004455 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4456 */
4457
4458 /* should be the usecases enabled in adev_open_input_stream() */
4459 static const int test_in_usecases[] = {
4460 USECASE_AUDIO_RECORD,
4461 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4462 };
4463 /* should be the usecases enabled in adev_open_output_stream()*/
4464 static const int test_out_usecases[] = {
4465 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4466 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4467 };
4468 static const usecase_type_t usecase_type_by_dir[] = {
4469 PCM_PLAYBACK,
4470 PCM_CAPTURE,
4471 };
4472 static const unsigned flags_by_dir[] = {
4473 PCM_OUT,
4474 PCM_IN,
4475 };
4476
4477 size_t i;
4478 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004479 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004480 char info[512]; /* for possible debug info */
4481
4482 for (dir = 0; dir < 2; ++dir) {
4483 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4484 const unsigned flags_dir = flags_by_dir[dir];
4485 const size_t testsize =
4486 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4487 const int *testcases =
4488 dir ? test_in_usecases : test_out_usecases;
4489 const audio_devices_t audio_device =
4490 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4491
4492 for (i = 0; i < testsize; ++i) {
4493 const audio_usecase_t audio_usecase = testcases[i];
4494 int device_id;
4495 snd_device_t snd_device;
4496 struct pcm_params **pparams;
4497 struct stream_out out;
4498 struct stream_in in;
4499 struct audio_usecase uc_info;
4500 int retval;
4501
4502 pparams = &adev->use_case_table[audio_usecase];
4503 pcm_params_free(*pparams); /* can accept null input */
4504 *pparams = NULL;
4505
4506 /* find the device ID for the use case (signed, for error) */
4507 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4508 if (device_id < 0)
4509 continue;
4510
4511 /* prepare structures for device probing */
4512 memset(&uc_info, 0, sizeof(uc_info));
4513 uc_info.id = audio_usecase;
4514 uc_info.type = usecase_type;
4515 if (dir) {
4516 adev->active_input = &in;
4517 memset(&in, 0, sizeof(in));
4518 in.device = audio_device;
4519 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4520 uc_info.stream.in = &in;
4521 } else {
4522 adev->active_input = NULL;
4523 }
4524 memset(&out, 0, sizeof(out));
4525 out.devices = audio_device; /* only field needed in select_devices */
4526 uc_info.stream.out = &out;
4527 uc_info.devices = audio_device;
4528 uc_info.in_snd_device = SND_DEVICE_NONE;
4529 uc_info.out_snd_device = SND_DEVICE_NONE;
4530 list_add_tail(&adev->usecase_list, &uc_info.list);
4531
4532 /* select device - similar to start_(in/out)put_stream() */
4533 retval = select_devices(adev, audio_usecase);
4534 if (retval >= 0) {
4535 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4536#if LOG_NDEBUG == 0
4537 if (*pparams) {
4538 ALOGV("%s: (%s) card %d device %d", __func__,
4539 dir ? "input" : "output", card_id, device_id);
4540 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004541 } else {
4542 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4543 }
4544#endif
4545 }
4546
4547 /* deselect device - similar to stop_(in/out)put_stream() */
4548 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004549 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004550 /* 2. Disable the rx device */
4551 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004552 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004553 list_remove(&uc_info.list);
4554 }
4555 }
4556 adev->active_input = NULL; /* restore adev state */
4557 return 0;
4558}
4559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560static int adev_close(hw_device_t *device)
4561{
Andy Hung31aca912014-03-20 17:14:59 -07004562 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004564
4565 if (!adev)
4566 return 0;
4567
4568 pthread_mutex_lock(&adev_init_lock);
4569
4570 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004571 audio_extn_snd_mon_unregister_listener(adev);
4572 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004573 audio_route_free(adev->audio_route);
4574 free(adev->snd_dev_ref_cnt);
4575 platform_deinit(adev->platform);
4576 audio_extn_extspk_deinit(adev->extspk);
4577 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004578 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004579 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4580 pcm_params_free(adev->use_case_table[i]);
4581 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004582 if (adev->adm_deinit)
4583 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004584 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004585 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004586
4587 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004588
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 return 0;
4590}
4591
Glenn Kasten4f993392014-05-14 07:30:48 -07004592/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4593 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4594 * just that it _might_ work.
4595 */
4596static int period_size_is_plausible_for_low_latency(int period_size)
4597{
4598 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004599 case 48:
4600 case 96:
4601 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004602 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004603 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004604 case 240:
4605 case 320:
4606 case 480:
4607 return 1;
4608 default:
4609 return 0;
4610 }
4611}
4612
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004613static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4614{
4615 int card;
4616 card_status_t status;
4617
4618 if (!parms)
4619 return;
4620
4621 if (parse_snd_card_status(parms, &card, &status) < 0)
4622 return;
4623
4624 pthread_mutex_lock(&adev->lock);
4625 bool valid_cb = (card == adev->snd_card);
4626 if (valid_cb) {
4627 if (adev->card_status != status) {
4628 adev->card_status = status;
4629 platform_snd_card_update(adev->platform, status);
4630 }
4631 }
4632 pthread_mutex_unlock(&adev->lock);
4633 return;
4634}
4635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636static int adev_open(const hw_module_t *module, const char *name,
4637 hw_device_t **device)
4638{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004639 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640
Eric Laurent2bafff12016-03-17 12:17:23 -07004641 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004642 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004643 pthread_mutex_lock(&adev_init_lock);
4644 if (audio_device_ref_count != 0) {
4645 *device = &adev->device.common;
4646 audio_device_ref_count++;
4647 ALOGV("%s: returning existing instance of adev", __func__);
4648 ALOGV("%s: exit", __func__);
4649 pthread_mutex_unlock(&adev_init_lock);
4650 return 0;
4651 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652 adev = calloc(1, sizeof(struct audio_device));
4653
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004654 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4655
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4657 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4658 adev->device.common.module = (struct hw_module_t *)module;
4659 adev->device.common.close = adev_close;
4660
4661 adev->device.init_check = adev_init_check;
4662 adev->device.set_voice_volume = adev_set_voice_volume;
4663 adev->device.set_master_volume = adev_set_master_volume;
4664 adev->device.get_master_volume = adev_get_master_volume;
4665 adev->device.set_master_mute = adev_set_master_mute;
4666 adev->device.get_master_mute = adev_get_master_mute;
4667 adev->device.set_mode = adev_set_mode;
4668 adev->device.set_mic_mute = adev_set_mic_mute;
4669 adev->device.get_mic_mute = adev_get_mic_mute;
4670 adev->device.set_parameters = adev_set_parameters;
4671 adev->device.get_parameters = adev_get_parameters;
4672 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4673 adev->device.open_output_stream = adev_open_output_stream;
4674 adev->device.close_output_stream = adev_close_output_stream;
4675 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004676
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677 adev->device.close_input_stream = adev_close_input_stream;
4678 adev->device.dump = adev_dump;
4679
4680 /* Set the default route before the PCM stream is opened */
4681 pthread_mutex_lock(&adev->lock);
4682 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004683 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004684 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004685 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004686 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004687 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004688 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004689 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004690 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004691 pthread_mutex_unlock(&adev->lock);
4692
4693 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004694 adev->platform = platform_init(adev);
4695 if (!adev->platform) {
4696 free(adev->snd_dev_ref_cnt);
4697 free(adev);
4698 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4699 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004700 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004701 return -EINVAL;
4702 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004703 adev->extspk = audio_extn_extspk_init(adev);
4704
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004705 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4706 if (adev->visualizer_lib == NULL) {
4707 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4708 } else {
4709 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4710 adev->visualizer_start_output =
4711 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4712 "visualizer_hal_start_output");
4713 adev->visualizer_stop_output =
4714 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4715 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004716 }
4717
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004718 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4719 if (adev->offload_effects_lib == NULL) {
4720 ALOGW("%s: DLOPEN failed for %s", __func__,
4721 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4722 } else {
4723 ALOGV("%s: DLOPEN successful for %s", __func__,
4724 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4725 adev->offload_effects_start_output =
4726 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4727 "offload_effects_bundle_hal_start_output");
4728 adev->offload_effects_stop_output =
4729 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4730 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004731 }
4732
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004733 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4734 if (adev->adm_lib == NULL) {
4735 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4736 } else {
4737 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4738 adev->adm_init = (adm_init_t)
4739 dlsym(adev->adm_lib, "adm_init");
4740 adev->adm_deinit = (adm_deinit_t)
4741 dlsym(adev->adm_lib, "adm_deinit");
4742 adev->adm_register_input_stream = (adm_register_input_stream_t)
4743 dlsym(adev->adm_lib, "adm_register_input_stream");
4744 adev->adm_register_output_stream = (adm_register_output_stream_t)
4745 dlsym(adev->adm_lib, "adm_register_output_stream");
4746 adev->adm_deregister_stream = (adm_deregister_stream_t)
4747 dlsym(adev->adm_lib, "adm_deregister_stream");
4748 adev->adm_request_focus = (adm_request_focus_t)
4749 dlsym(adev->adm_lib, "adm_request_focus");
4750 adev->adm_abandon_focus = (adm_abandon_focus_t)
4751 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004752 adev->adm_set_config = (adm_set_config_t)
4753 dlsym(adev->adm_lib, "adm_set_config");
4754 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4755 dlsym(adev->adm_lib, "adm_request_focus_v2");
4756 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4757 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4758 adev->adm_on_routing_change = (adm_on_routing_change_t)
4759 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004760 }
4761
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004762 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004763 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004766
Andy Hung31aca912014-03-20 17:14:59 -07004767 if (k_enable_extended_precision)
4768 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769
Glenn Kasten4f993392014-05-14 07:30:48 -07004770 char value[PROPERTY_VALUE_MAX];
4771 int trial;
4772 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4773 trial = atoi(value);
4774 if (period_size_is_plausible_for_low_latency(trial)) {
4775 pcm_config_low_latency.period_size = trial;
4776 pcm_config_low_latency.start_threshold = trial / 4;
4777 pcm_config_low_latency.avail_min = trial / 4;
4778 configured_low_latency_capture_period_size = trial;
4779 }
4780 }
4781 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4782 trial = atoi(value);
4783 if (period_size_is_plausible_for_low_latency(trial)) {
4784 configured_low_latency_capture_period_size = trial;
4785 }
4786 }
4787
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004788 // commented as full set of app type cfg is sent from platform
4789 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004790 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004791
4792 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4793 af_period_multiplier = atoi(value);
4794 if (af_period_multiplier < 0) {
4795 af_period_multiplier = 2;
4796 } else if (af_period_multiplier > 4) {
4797 af_period_multiplier = 4;
4798 }
4799 ALOGV("new period_multiplier = %d", af_period_multiplier);
4800 }
4801
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004802 audio_extn_tfa_98xx_init(adev);
4803
vivek mehta1a9b7c02015-06-25 11:49:38 -07004804 pthread_mutex_unlock(&adev_init_lock);
4805
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004806 if (adev->adm_init)
4807 adev->adm_data = adev->adm_init();
4808
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004809 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004810 audio_extn_snd_mon_init();
4811 pthread_mutex_lock(&adev->lock);
4812 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4813 adev->card_status = CARD_STATUS_ONLINE;
4814 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004815 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004816
Eric Laurent2bafff12016-03-17 12:17:23 -07004817 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004818 return 0;
4819}
4820
4821static struct hw_module_methods_t hal_module_methods = {
4822 .open = adev_open,
4823};
4824
4825struct audio_module HAL_MODULE_INFO_SYM = {
4826 .common = {
4827 .tag = HARDWARE_MODULE_TAG,
4828 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4829 .hal_api_version = HARDWARE_HAL_API_VERSION,
4830 .id = AUDIO_HARDWARE_MODULE_ID,
4831 .name = "QCOM Audio HAL",
4832 .author = "Code Aurora Forum",
4833 .methods = &hal_module_methods,
4834 },
4835};