blob: 63f6101cf13f1a24b7e25e7061ba9029ad6edf8a [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 &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700869 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
870 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700871 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
873 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700874 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700875 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700876 switch_device[usecase->id] = true;
877 num_uc_to_switch++;
878 }
879 }
880
881 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 list_for_each(node, &adev->usecase_list) {
883 usecase = node_to_item(node, struct audio_usecase, list);
884 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700885 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900886 }
887 }
888
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700889 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900890 list_for_each(node, &adev->usecase_list) {
891 usecase = node_to_item(node, struct audio_usecase, list);
892 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700893 d_device = derive_playback_snd_device(usecase, uc_info,
894 snd_device);
895 enable_snd_device(adev, d_device);
896 /* Update the out_snd_device before enabling the audio route */
897 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 }
899 }
900
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 /* Re-route all the usecases on the shared backend other than the
902 specified usecase to new snd devices */
903 list_for_each(node, &adev->usecase_list) {
904 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700906 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700907 }
908 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 }
910}
911
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700912static void check_and_route_capture_usecases(struct audio_device *adev,
913 struct audio_usecase *uc_info,
914 snd_device_t snd_device)
915{
916 struct listnode *node;
917 struct audio_usecase *usecase;
918 bool switch_device[AUDIO_USECASE_MAX];
919 int i, num_uc_to_switch = 0;
920
vivek mehta4ed66e62016-04-15 23:33:34 -0700921 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
922
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700923 /*
924 * This function is to make sure that all the active capture usecases
925 * are always routed to the same input sound device.
926 * For example, if audio-record and voice-call usecases are currently
927 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
928 * is received for voice call then we have to make sure that audio-record
929 * usecase is also switched to earpiece i.e. voice-dmic-ef,
930 * because of the limitation that two devices cannot be enabled
931 * at the same time if they share the same backend.
932 */
933 for (i = 0; i < AUDIO_USECASE_MAX; i++)
934 switch_device[i] = false;
935
936 list_for_each(node, &adev->usecase_list) {
937 usecase = node_to_item(node, struct audio_usecase, list);
938 if (usecase->type != PCM_PLAYBACK &&
939 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700940 usecase->in_snd_device != snd_device &&
941 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700942 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
943 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700944 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700945 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700946 switch_device[usecase->id] = true;
947 num_uc_to_switch++;
948 }
949 }
950
951 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700952 list_for_each(node, &adev->usecase_list) {
953 usecase = node_to_item(node, struct audio_usecase, list);
954 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700955 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700956 }
957 }
958
959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700962 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700963 }
964 }
965
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700966 /* Re-route all the usecases on the shared backend other than the
967 specified usecase to new snd devices */
968 list_for_each(node, &adev->usecase_list) {
969 usecase = node_to_item(node, struct audio_usecase, list);
970 /* Update the in_snd_device only before enabling the audio route */
971 if (switch_device[usecase->id] ) {
972 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700973 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700974 }
975 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700976 }
977}
978
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800979/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700980static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700982 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700983 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800984
985 switch (channels) {
986 /*
987 * Do not handle stereo output in Multi-channel cases
988 * Stereo case is handled in normal playback path
989 */
990 case 6:
991 ALOGV("%s: HDMI supports 5.1", __func__);
992 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
993 break;
994 case 8:
995 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
996 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
997 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
998 break;
999 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001000 ALOGE("HDMI does not support multi channel playback");
1001 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002 break;
1003 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001004 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005}
1006
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001007static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1008 uint32_t *supported_sample_rates __unused,
1009 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001011 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1012 supported_sample_rates,
1013 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001014#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015 for (ssize_t i=0; i<count; i++) {
1016 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1017 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001018 }
1019#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001020 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001021}
1022
Haynes Mathew George569b7482017-05-08 14:44:27 -07001023static int read_usb_sup_channel_masks(bool is_playback,
1024 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001025 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001026{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001027 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001028 int channel_count;
1029 uint32_t num_masks = 0;
1030 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1031 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001032 }
Eric Laurent74b55762017-07-09 17:04:53 -07001033 if (is_playback) {
1034 // For playback we never report mono because the framework always outputs stereo
1035 channel_count = DEFAULT_CHANNEL_COUNT;
1036 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1037 // above 2 but we want indexed masks here. So we
1038 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1039 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1040 }
1041 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1042 supported_channel_masks[num_masks++] =
1043 audio_channel_mask_for_index_assignment_from_count(channel_count);
1044 }
1045 } else {
1046 // For capture we report all supported channel masks from 1 channel up.
1047 channel_count = MIN_CHANNEL_COUNT;
1048 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1049 // indexed mask
1050 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1051 supported_channel_masks[num_masks++] =
1052 audio_channel_in_mask_from_count(channel_count);
1053 }
1054 }
1055 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1056 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1057 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001058}
1059
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001060static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001061 audio_format_t *supported_formats,
1062 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001063{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001064 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001065 switch (bitwidth) {
1066 case 24:
1067 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001068 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001069 break;
1070 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001071 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001072 break;
1073 case 16:
1074 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001075 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001076 break;
1077 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001078 ALOGV("%s: %s supported format %d", __func__,
1079 is_playback ? "P" : "C", bitwidth);
1080 return 1;
1081}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001082
Haynes Mathew George569b7482017-05-08 14:44:27 -07001083static int read_usb_sup_params_and_compare(bool is_playback,
1084 audio_format_t *format,
1085 audio_format_t *supported_formats,
1086 uint32_t max_formats,
1087 audio_channel_mask_t *mask,
1088 audio_channel_mask_t *supported_channel_masks,
1089 uint32_t max_masks,
1090 uint32_t *rate,
1091 uint32_t *supported_sample_rates,
1092 uint32_t max_rates) {
1093 int ret = 0;
1094 int num_formats;
1095 int num_masks;
1096 int num_rates;
1097 int i;
1098
1099 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1100 max_formats);
1101 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1102 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001103
Haynes Mathew George569b7482017-05-08 14:44:27 -07001104 num_rates = read_usb_sup_sample_rates(is_playback,
1105 supported_sample_rates, max_rates);
1106
1107#define LUT(table, len, what, dflt) \
1108 for (i=0; i<len && (table[i] != what); i++); \
1109 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1110
1111 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1112 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1113 LUT(supported_sample_rates, num_rates, *rate, 0);
1114
1115#undef LUT
1116 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001117}
1118
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001119static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1120{
1121 struct audio_usecase *usecase;
1122 struct listnode *node;
1123
1124 list_for_each(node, &adev->usecase_list) {
1125 usecase = node_to_item(node, struct audio_usecase, list);
1126 if (usecase->type == VOICE_CALL) {
1127 ALOGV("%s: usecase id %d", __func__, usecase->id);
1128 return usecase->id;
1129 }
1130 }
1131 return USECASE_INVALID;
1132}
1133
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001134struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1135 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001136{
1137 struct audio_usecase *usecase;
1138 struct listnode *node;
1139
1140 list_for_each(node, &adev->usecase_list) {
1141 usecase = node_to_item(node, struct audio_usecase, list);
1142 if (usecase->id == uc_id)
1143 return usecase;
1144 }
1145 return NULL;
1146}
1147
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001148int select_devices(struct audio_device *adev,
1149 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001151 snd_device_t out_snd_device = SND_DEVICE_NONE;
1152 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001153 struct audio_usecase *usecase = NULL;
1154 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001155 struct audio_usecase *hfp_usecase = NULL;
1156 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001157 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001159
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001160 usecase = get_usecase_from_list(adev, uc_id);
1161 if (usecase == NULL) {
1162 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1163 return -EINVAL;
1164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001165
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001166 if ((usecase->type == VOICE_CALL) ||
1167 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001168 out_snd_device = platform_get_output_snd_device(adev->platform,
1169 usecase->stream.out->devices);
1170 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171 usecase->devices = usecase->stream.out->devices;
1172 } else {
1173 /*
1174 * If the voice call is active, use the sound devices of voice call usecase
1175 * so that it would not result any device switch. All the usecases will
1176 * be switched to new device when select_devices() is called for voice call
1177 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001178 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001180 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001181 vc_usecase = get_usecase_from_list(adev,
1182 get_voice_usecase_id_from_list(adev));
1183 if ((vc_usecase != NULL) &&
1184 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1185 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001186 in_snd_device = vc_usecase->in_snd_device;
1187 out_snd_device = vc_usecase->out_snd_device;
1188 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001189 } else if (audio_extn_hfp_is_active(adev)) {
1190 hfp_ucid = audio_extn_hfp_get_usecase();
1191 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1192 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1193 in_snd_device = hfp_usecase->in_snd_device;
1194 out_snd_device = hfp_usecase->out_snd_device;
1195 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001196 }
1197 if (usecase->type == PCM_PLAYBACK) {
1198 usecase->devices = usecase->stream.out->devices;
1199 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001200 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001201 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001203 if (usecase->stream.out == adev->primary_output &&
1204 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001205 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1206 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001207 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001208 select_devices(adev, adev->active_input->usecase);
1209 }
1210 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001211 } else if (usecase->type == PCM_CAPTURE) {
1212 usecase->devices = usecase->stream.in->device;
1213 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001214 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001215 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001216 if (adev->active_input &&
1217 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1218 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001219 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001220 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1221 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1222 } else if (adev->primary_output) {
1223 out_device = adev->primary_output->devices;
1224 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001225 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001226 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001227 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001228 }
1229 }
1230
1231 if (out_snd_device == usecase->out_snd_device &&
1232 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001233 return 0;
1234 }
1235
Eric Laurent2bafff12016-03-17 12:17:23 -07001236 if (out_snd_device != SND_DEVICE_NONE &&
1237 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1238 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1239 __func__,
1240 use_case_table[uc_id],
1241 adev->last_logged_snd_device[uc_id][0],
1242 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1243 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1244 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1245 -1,
1246 out_snd_device,
1247 platform_get_snd_device_name(out_snd_device),
1248 platform_get_snd_device_acdb_id(out_snd_device));
1249 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1250 }
1251 if (in_snd_device != SND_DEVICE_NONE &&
1252 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1253 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1254 __func__,
1255 use_case_table[uc_id],
1256 adev->last_logged_snd_device[uc_id][1],
1257 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1258 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1259 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1260 -1,
1261 in_snd_device,
1262 platform_get_snd_device_name(in_snd_device),
1263 platform_get_snd_device_acdb_id(in_snd_device));
1264 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1265 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001266
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267 /*
1268 * Limitation: While in call, to do a device switch we need to disable
1269 * and enable both RX and TX devices though one of them is same as current
1270 * device.
1271 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001272 if ((usecase->type == VOICE_CALL) &&
1273 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1274 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001275 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001276 /* Disable sidetone only if voice call already exists */
1277 if (voice_is_call_state_active(adev))
1278 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001279 }
1280
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001281 /* Disable current sound devices */
1282 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001283 disable_audio_route(adev, usecase);
1284 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001285 }
1286
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001287 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001288 disable_audio_route(adev, usecase);
1289 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001290 }
1291
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001292 /* Applicable only on the targets that has external modem.
1293 * New device information should be sent to modem before enabling
1294 * the devices to reduce in-call device switch time.
1295 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001296 if ((usecase->type == VOICE_CALL) &&
1297 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1298 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001299 status = platform_switch_voice_call_enable_device_config(adev->platform,
1300 out_snd_device,
1301 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001302 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001303
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001304 /* Enable new sound devices */
1305 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001306 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001307 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001308 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001309 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 }
1311
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001312 if (in_snd_device != SND_DEVICE_NONE) {
1313 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001314 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001315 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316
Eric Laurentb23d5282013-05-14 15:27:20 -07001317 if (usecase->type == VOICE_CALL)
1318 status = platform_switch_voice_call_device_post(adev->platform,
1319 out_snd_device,
1320 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001321
sangwoo170731f2013-06-08 15:36:36 +09001322 usecase->in_snd_device = in_snd_device;
1323 usecase->out_snd_device = out_snd_device;
1324
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001325 audio_extn_tfa_98xx_set_mode();
1326
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001327 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001328
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001329 /* Applicable only on the targets that has external modem.
1330 * Enable device command should be sent to modem only after
1331 * enabling voice call mixer controls
1332 */
vivek mehta765eb642015-08-07 19:46:06 -07001333 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001334 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1335 out_snd_device,
1336 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001337 /* Enable sidetone only if voice call already exists */
1338 if (voice_is_call_state_active(adev))
1339 voice_set_sidetone(adev, out_snd_device, true);
1340 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001342 return status;
1343}
1344
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001345static int stop_input_stream(struct stream_in *in)
1346{
1347 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348 struct audio_usecase *uc_info;
1349 struct audio_device *adev = in->dev;
1350
Eric Laurent994a6932013-07-17 11:51:42 -07001351 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001353
1354 if (adev->active_input) {
1355 if (adev->active_input->usecase == in->usecase) {
1356 adev->active_input = NULL;
1357 } else {
1358 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1359 __func__,
1360 use_case_table[adev->active_input->usecase],
1361 use_case_table[in->usecase]);
1362 }
1363 }
1364
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001365 uc_info = get_usecase_from_list(adev, in->usecase);
1366 if (uc_info == NULL) {
1367 ALOGE("%s: Could not find the usecase (%d) in the list",
1368 __func__, in->usecase);
1369 return -EINVAL;
1370 }
1371
vivek mehta781065c2017-04-04 12:55:01 -07001372 /* Close in-call recording streams */
1373 voice_check_and_stop_incall_rec_usecase(adev, in);
1374
Eric Laurent150dbfe2013-02-27 14:31:02 -08001375 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001376 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001377
1378 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001379 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001380
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001381 list_remove(&uc_info->list);
1382 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001383
Eric Laurent994a6932013-07-17 11:51:42 -07001384 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001385 return ret;
1386}
1387
1388int start_input_stream(struct stream_in *in)
1389{
1390 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001391 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001392 struct audio_usecase *uc_info;
1393 struct audio_device *adev = in->dev;
1394
Eric Laurent994a6932013-07-17 11:51:42 -07001395 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001396
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001397 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1398 return -EIO;
1399
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001400 if (in->card_status == CARD_STATUS_OFFLINE ||
1401 adev->card_status == CARD_STATUS_OFFLINE) {
1402 ALOGW("in->card_status or adev->card_status offline, try again");
1403 ret = -EAGAIN;
1404 goto error_config;
1405 }
1406
vivek mehta781065c2017-04-04 12:55:01 -07001407 /* Check if source matches incall recording usecase criteria */
1408 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1409 if (ret)
1410 goto error_config;
1411 else
1412 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1413
Eric Laurentb23d5282013-05-14 15:27:20 -07001414 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001415 if (in->pcm_device_id < 0) {
1416 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1417 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001418 ret = -EINVAL;
1419 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001421
1422 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001423 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1424 uc_info->id = in->usecase;
1425 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001426 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001427 uc_info->devices = in->device;
1428 uc_info->in_snd_device = SND_DEVICE_NONE;
1429 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001430
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001431 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001432
1433 audio_extn_perf_lock_acquire();
1434
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001435 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436
Eric Laurent0e46adf2016-12-16 12:49:24 -08001437 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001438 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001439 ALOGE("%s: pcm stream not ready", __func__);
1440 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001441 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001442 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001443 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001444 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1445 goto error_open;
1446 }
1447 } else {
1448 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1449 unsigned int pcm_open_retry_count = 0;
1450
1451 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1452 flags |= PCM_MMAP | PCM_NOIRQ;
1453 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1454 } else if (in->realtime) {
1455 flags |= PCM_MMAP | PCM_NOIRQ;
1456 }
1457
1458 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1459 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1460
1461 while (1) {
1462 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1463 flags, &in->config);
1464 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1465 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1466 if (in->pcm != NULL) {
1467 pcm_close(in->pcm);
1468 in->pcm = NULL;
1469 }
1470 if (pcm_open_retry_count-- == 0) {
1471 ret = -EIO;
1472 goto error_open;
1473 }
1474 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1475 continue;
1476 }
1477 break;
1478 }
1479
1480 ALOGV("%s: pcm_prepare", __func__);
1481 ret = pcm_prepare(in->pcm);
1482 if (ret < 0) {
1483 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001484 pcm_close(in->pcm);
1485 in->pcm = NULL;
1486 goto error_open;
1487 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001488 if (in->realtime) {
1489 ret = pcm_start(in->pcm);
1490 if (ret < 0) {
1491 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1492 pcm_close(in->pcm);
1493 in->pcm = NULL;
1494 goto error_open;
1495 }
1496 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001497 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001498 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001499 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001500 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001501
Eric Laurent0e46adf2016-12-16 12:49:24 -08001502 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001503
1504error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001506 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001507
1508error_config:
1509 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001510 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001511 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512}
1513
Eric Laurenta1478072015-09-21 17:21:52 -07001514void lock_input_stream(struct stream_in *in)
1515{
1516 pthread_mutex_lock(&in->pre_lock);
1517 pthread_mutex_lock(&in->lock);
1518 pthread_mutex_unlock(&in->pre_lock);
1519}
1520
1521void lock_output_stream(struct stream_out *out)
1522{
1523 pthread_mutex_lock(&out->pre_lock);
1524 pthread_mutex_lock(&out->lock);
1525 pthread_mutex_unlock(&out->pre_lock);
1526}
1527
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001528/* must be called with out->lock locked */
1529static int send_offload_cmd_l(struct stream_out* out, int command)
1530{
1531 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1532
1533 ALOGVV("%s %d", __func__, command);
1534
1535 cmd->cmd = command;
1536 list_add_tail(&out->offload_cmd_list, &cmd->node);
1537 pthread_cond_signal(&out->offload_cond);
1538 return 0;
1539}
1540
1541/* must be called iwth out->lock locked */
1542static void stop_compressed_output_l(struct stream_out *out)
1543{
1544 out->offload_state = OFFLOAD_STATE_IDLE;
1545 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001546 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001547 if (out->compr != NULL) {
1548 compress_stop(out->compr);
1549 while (out->offload_thread_blocked) {
1550 pthread_cond_wait(&out->cond, &out->lock);
1551 }
1552 }
1553}
1554
1555static void *offload_thread_loop(void *context)
1556{
1557 struct stream_out *out = (struct stream_out *) context;
1558 struct listnode *item;
1559
1560 out->offload_state = OFFLOAD_STATE_IDLE;
1561 out->playback_started = 0;
1562
1563 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1564 set_sched_policy(0, SP_FOREGROUND);
1565 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1566
1567 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001568 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001569 for (;;) {
1570 struct offload_cmd *cmd = NULL;
1571 stream_callback_event_t event;
1572 bool send_callback = false;
1573
1574 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1575 __func__, list_empty(&out->offload_cmd_list),
1576 out->offload_state);
1577 if (list_empty(&out->offload_cmd_list)) {
1578 ALOGV("%s SLEEPING", __func__);
1579 pthread_cond_wait(&out->offload_cond, &out->lock);
1580 ALOGV("%s RUNNING", __func__);
1581 continue;
1582 }
1583
1584 item = list_head(&out->offload_cmd_list);
1585 cmd = node_to_item(item, struct offload_cmd, node);
1586 list_remove(item);
1587
1588 ALOGVV("%s STATE %d CMD %d out->compr %p",
1589 __func__, out->offload_state, cmd->cmd, out->compr);
1590
1591 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1592 free(cmd);
1593 break;
1594 }
1595
1596 if (out->compr == NULL) {
1597 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001598 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001599 pthread_cond_signal(&out->cond);
1600 continue;
1601 }
1602 out->offload_thread_blocked = true;
1603 pthread_mutex_unlock(&out->lock);
1604 send_callback = false;
1605 switch(cmd->cmd) {
1606 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1607 compress_wait(out->compr, -1);
1608 send_callback = true;
1609 event = STREAM_CBK_EVENT_WRITE_READY;
1610 break;
1611 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001612 compress_next_track(out->compr);
1613 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001614 send_callback = true;
1615 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001616 /* Resend the metadata for next iteration */
1617 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001618 break;
1619 case OFFLOAD_CMD_DRAIN:
1620 compress_drain(out->compr);
1621 send_callback = true;
1622 event = STREAM_CBK_EVENT_DRAIN_READY;
1623 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001624 case OFFLOAD_CMD_ERROR:
1625 send_callback = true;
1626 event = STREAM_CBK_EVENT_ERROR;
1627 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001628 default:
1629 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1630 break;
1631 }
Eric Laurenta1478072015-09-21 17:21:52 -07001632 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001633 out->offload_thread_blocked = false;
1634 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001635 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001636 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001637 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001638 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001639 free(cmd);
1640 }
1641
1642 pthread_cond_signal(&out->cond);
1643 while (!list_empty(&out->offload_cmd_list)) {
1644 item = list_head(&out->offload_cmd_list);
1645 list_remove(item);
1646 free(node_to_item(item, struct offload_cmd, node));
1647 }
1648 pthread_mutex_unlock(&out->lock);
1649
1650 return NULL;
1651}
1652
1653static int create_offload_callback_thread(struct stream_out *out)
1654{
1655 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1656 list_init(&out->offload_cmd_list);
1657 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1658 offload_thread_loop, out);
1659 return 0;
1660}
1661
1662static int destroy_offload_callback_thread(struct stream_out *out)
1663{
Eric Laurenta1478072015-09-21 17:21:52 -07001664 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001665 stop_compressed_output_l(out);
1666 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1667
1668 pthread_mutex_unlock(&out->lock);
1669 pthread_join(out->offload_thread, (void **) NULL);
1670 pthread_cond_destroy(&out->offload_cond);
1671
1672 return 0;
1673}
1674
Eric Laurent07eeafd2013-10-06 12:52:49 -07001675static bool allow_hdmi_channel_config(struct audio_device *adev)
1676{
1677 struct listnode *node;
1678 struct audio_usecase *usecase;
1679 bool ret = true;
1680
1681 list_for_each(node, &adev->usecase_list) {
1682 usecase = node_to_item(node, struct audio_usecase, list);
1683 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1684 /*
1685 * If voice call is already existing, do not proceed further to avoid
1686 * disabling/enabling both RX and TX devices, CSD calls, etc.
1687 * Once the voice call done, the HDMI channels can be configured to
1688 * max channels of remaining use cases.
1689 */
1690 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001691 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001692 __func__);
1693 ret = false;
1694 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001695 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1696 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001697 "no change in HDMI channels", __func__);
1698 ret = false;
1699 break;
1700 }
1701 }
1702 }
1703 return ret;
1704}
1705
1706static int check_and_set_hdmi_channels(struct audio_device *adev,
1707 unsigned int channels)
1708{
1709 struct listnode *node;
1710 struct audio_usecase *usecase;
1711
1712 /* Check if change in HDMI channel config is allowed */
1713 if (!allow_hdmi_channel_config(adev))
1714 return 0;
1715
1716 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001717 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001718 return 0;
1719 }
1720
1721 platform_set_hdmi_channels(adev->platform, channels);
1722 adev->cur_hdmi_channels = channels;
1723
1724 /*
1725 * Deroute all the playback streams routed to HDMI so that
1726 * the back end is deactivated. Note that backend will not
1727 * be deactivated if any one stream is connected to it.
1728 */
1729 list_for_each(node, &adev->usecase_list) {
1730 usecase = node_to_item(node, struct audio_usecase, list);
1731 if (usecase->type == PCM_PLAYBACK &&
1732 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001733 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001734 }
1735 }
1736
1737 /*
1738 * Enable all the streams disabled above. Now the HDMI backend
1739 * will be activated with new channel configuration
1740 */
1741 list_for_each(node, &adev->usecase_list) {
1742 usecase = node_to_item(node, struct audio_usecase, list);
1743 if (usecase->type == PCM_PLAYBACK &&
1744 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001745 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001746 }
1747 }
1748
1749 return 0;
1750}
1751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752static int stop_output_stream(struct stream_out *out)
1753{
1754 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001755 struct audio_usecase *uc_info;
1756 struct audio_device *adev = out->dev;
1757
Eric Laurent994a6932013-07-17 11:51:42 -07001758 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001759 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760 uc_info = get_usecase_from_list(adev, out->usecase);
1761 if (uc_info == NULL) {
1762 ALOGE("%s: Could not find the usecase (%d) in the list",
1763 __func__, out->usecase);
1764 return -EINVAL;
1765 }
1766
Haynes Mathew George41f86652014-06-17 14:22:15 -07001767 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1768 if (adev->visualizer_stop_output != NULL)
1769 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1770 if (adev->offload_effects_stop_output != NULL)
1771 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1772 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001773
Eric Laurent150dbfe2013-02-27 14:31:02 -08001774 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001775 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001776
1777 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001778 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001780 list_remove(&uc_info->list);
1781 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782
Eric Laurent0499d4f2014-08-25 22:39:29 -05001783 audio_extn_extspk_update(adev->extspk);
1784
Eric Laurent07eeafd2013-10-06 12:52:49 -07001785 /* Must be called after removing the usecase from list */
1786 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1787 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1788
Eric Laurent994a6932013-07-17 11:51:42 -07001789 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790 return ret;
1791}
1792
1793int start_output_stream(struct stream_out *out)
1794{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 struct audio_usecase *uc_info;
1797 struct audio_device *adev = out->dev;
1798
Eric Laurent994a6932013-07-17 11:51:42 -07001799 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001800 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001801
1802 if (out->card_status == CARD_STATUS_OFFLINE ||
1803 adev->card_status == CARD_STATUS_OFFLINE) {
1804 ALOGW("out->card_status or adev->card_status offline, try again");
1805 ret = -EAGAIN;
1806 goto error_config;
1807 }
1808
Eric Laurentb23d5282013-05-14 15:27:20 -07001809 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001810 if (out->pcm_device_id < 0) {
1811 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1812 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001813 ret = -EINVAL;
1814 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001815 }
1816
1817 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1818 uc_info->id = out->usecase;
1819 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001820 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001821 uc_info->devices = out->devices;
1822 uc_info->in_snd_device = SND_DEVICE_NONE;
1823 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824
Eric Laurent07eeafd2013-10-06 12:52:49 -07001825 /* This must be called before adding this usecase to the list */
1826 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1827 check_and_set_hdmi_channels(adev, out->config.channels);
1828
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001829 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001830
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001831 audio_extn_perf_lock_acquire();
1832
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001833 select_devices(adev, out->usecase);
1834
Eric Laurent0499d4f2014-08-25 22:39:29 -05001835 audio_extn_extspk_update(adev->extspk);
1836
Andy Hung31aca912014-03-20 17:14:59 -07001837 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001838 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001839 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1840 out->pcm = NULL;
1841 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1842 COMPRESS_IN, &out->compr_config);
1843 if (out->compr && !is_compress_ready(out->compr)) {
1844 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1845 compress_close(out->compr);
1846 out->compr = NULL;
1847 ret = -EIO;
1848 goto error_open;
1849 }
1850 if (out->offload_callback)
1851 compress_nonblock(out->compr, out->non_blocking);
1852
1853 if (adev->visualizer_start_output != NULL)
1854 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1855 if (adev->offload_effects_start_output != NULL)
1856 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1857 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001858 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001859 ALOGE("%s: pcm stream not ready", __func__);
1860 goto error_open;
1861 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001862 ret = pcm_start(out->pcm);
1863 if (ret < 0) {
1864 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1865 goto error_open;
1866 }
1867 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001868 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001869 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001870
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001871 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1872 flags |= PCM_MMAP | PCM_NOIRQ;
1873 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001874 } else if (out->realtime) {
1875 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001876 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001877
1878 while (1) {
1879 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1880 flags, &out->config);
1881 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1882 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1883 if (out->pcm != NULL) {
1884 pcm_close(out->pcm);
1885 out->pcm = NULL;
1886 }
1887 if (pcm_open_retry_count-- == 0) {
1888 ret = -EIO;
1889 goto error_open;
1890 }
1891 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1892 continue;
1893 }
1894 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001895 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001896 ALOGV("%s: pcm_prepare", __func__);
1897 if (pcm_is_ready(out->pcm)) {
1898 ret = pcm_prepare(out->pcm);
1899 if (ret < 0) {
1900 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1901 pcm_close(out->pcm);
1902 out->pcm = NULL;
1903 goto error_open;
1904 }
1905 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001906 if (out->realtime) {
1907 ret = pcm_start(out->pcm);
1908 if (ret < 0) {
1909 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1910 pcm_close(out->pcm);
1911 out->pcm = NULL;
1912 goto error_open;
1913 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001914 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001915 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001916 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001917 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001918 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001919 audio_extn_utils_send_app_type_gain(out->dev,
1920 out->app_type_cfg.app_type,
1921 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001922
1923 // consider a scenario where on pause lower layers are tear down.
1924 // so on resume, swap mixer control need to be sent only when
1925 // backend is active, hence rather than sending from enable device
1926 // sending it from start of streamtream
1927
1928 platform_set_swap_channels(adev, true);
1929
Eric Laurent994a6932013-07-17 11:51:42 -07001930 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001931 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001932error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001933 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001935error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001936 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937}
1938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939static int check_input_parameters(uint32_t sample_rate,
1940 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001941 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001943 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1944 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001945 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1946 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001947 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1948 return -EINVAL;
1949 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950
Eric Laurent74b55762017-07-09 17:04:53 -07001951 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1952 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001953 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001954 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001955 return -EINVAL;
1956 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001957
1958 switch (sample_rate) {
1959 case 8000:
1960 case 11025:
1961 case 12000:
1962 case 16000:
1963 case 22050:
1964 case 24000:
1965 case 32000:
1966 case 44100:
1967 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001968 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969 break;
1970 default:
vivek mehtadae44712015-07-27 14:13:18 -07001971 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972 return -EINVAL;
1973 }
1974
1975 return 0;
1976}
1977
vivek mehtaa68fea62017-06-08 19:04:02 -07001978static size_t get_stream_buffer_size(size_t duration_ms,
1979 uint32_t sample_rate,
1980 audio_format_t format,
1981 int channel_count,
1982 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983{
1984 size_t size = 0;
1985
vivek mehtaa68fea62017-06-08 19:04:02 -07001986 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001987 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001988 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001989
1990 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991
Glenn Kasten4f993392014-05-14 07:30:48 -07001992 /* make sure the size is multiple of 32 bytes
1993 * At 48 kHz mono 16-bit PCM:
1994 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1995 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1996 */
1997 size += 0x1f;
1998 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001999
2000 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001}
2002
2003static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2004{
2005 struct stream_out *out = (struct stream_out *)stream;
2006
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002007 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002008}
2009
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002010static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011{
2012 return -ENOSYS;
2013}
2014
2015static size_t out_get_buffer_size(const struct audio_stream *stream)
2016{
2017 struct stream_out *out = (struct stream_out *)stream;
2018
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2020 return out->compr_config.fragment_size;
2021 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002022 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002023 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024}
2025
2026static uint32_t out_get_channels(const struct audio_stream *stream)
2027{
2028 struct stream_out *out = (struct stream_out *)stream;
2029
2030 return out->channel_mask;
2031}
2032
2033static audio_format_t out_get_format(const struct audio_stream *stream)
2034{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002035 struct stream_out *out = (struct stream_out *)stream;
2036
2037 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002038}
2039
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002040static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041{
2042 return -ENOSYS;
2043}
2044
2045static int out_standby(struct audio_stream *stream)
2046{
2047 struct stream_out *out = (struct stream_out *)stream;
2048 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002049 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002050
Eric Laurent994a6932013-07-17 11:51:42 -07002051 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002052 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002053
Eric Laurenta1478072015-09-21 17:21:52 -07002054 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002055 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002056 if (adev->adm_deregister_stream)
2057 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002058 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002060 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2061 if (out->pcm) {
2062 pcm_close(out->pcm);
2063 out->pcm = NULL;
2064 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002065 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002066 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002067 out->playback_started = false;
2068 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002069 } else {
2070 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002071 out->gapless_mdata.encoder_delay = 0;
2072 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002073 if (out->compr != NULL) {
2074 compress_close(out->compr);
2075 out->compr = NULL;
2076 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002077 }
Phil Burkbc991042017-02-24 08:06:44 -08002078 if (do_stop) {
2079 stop_output_stream(out);
2080 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002081 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002082 }
2083 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002084 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002085 return 0;
2086}
2087
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002088static int out_on_error(struct audio_stream *stream)
2089{
2090 struct stream_out *out = (struct stream_out *)stream;
2091 struct audio_device *adev = out->dev;
2092 bool do_standby = false;
2093
2094 lock_output_stream(out);
2095 if (!out->standby) {
2096 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2097 stop_compressed_output_l(out);
2098 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2099 } else
2100 do_standby = true;
2101 }
2102 pthread_mutex_unlock(&out->lock);
2103
2104 if (do_standby)
2105 return out_standby(&out->stream.common);
2106
2107 return 0;
2108}
2109
Andy Hung7401c7c2016-09-21 12:41:21 -07002110static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111{
Andy Hung7401c7c2016-09-21 12:41:21 -07002112 struct stream_out *out = (struct stream_out *)stream;
2113
2114 // We try to get the lock for consistency,
2115 // but it isn't necessary for these variables.
2116 // If we're not in standby, we may be blocked on a write.
2117 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2118 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2119 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2120
2121 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002122 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002123 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002124
2125 // dump error info
2126 (void)error_log_dump(
2127 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002128 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002129 (void)power_log_dump(
2130 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 return 0;
2132}
2133
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002134static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2135{
2136 int ret = 0;
2137 char value[32];
2138 struct compr_gapless_mdata tmp_mdata;
2139
2140 if (!out || !parms) {
2141 return -EINVAL;
2142 }
2143
2144 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2145 if (ret >= 0) {
2146 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2147 } else {
2148 return -EINVAL;
2149 }
2150
2151 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2152 if (ret >= 0) {
2153 tmp_mdata.encoder_padding = atoi(value);
2154 } else {
2155 return -EINVAL;
2156 }
2157
2158 out->gapless_mdata = tmp_mdata;
2159 out->send_new_metadata = 1;
2160 ALOGV("%s new encoder delay %u and padding %u", __func__,
2161 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2162
2163 return 0;
2164}
2165
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002166static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2167{
2168 return out == adev->primary_output || out == adev->voice_tx_output;
2169}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2172{
2173 struct stream_out *out = (struct stream_out *)stream;
2174 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002175 struct audio_usecase *usecase;
2176 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002177 struct str_parms *parms;
2178 char value[32];
2179 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002180 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002181 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182
Eric Laurent2e140aa2016-06-30 17:14:46 -07002183 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002184 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185 parms = str_parms_create_str(kvpairs);
2186 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2187 if (ret >= 0) {
2188 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002189 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002190 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002192 /*
2193 * When HDMI cable is unplugged the music playback is paused and
2194 * the policy manager sends routing=0. But the audioflinger
2195 * continues to write data until standby time (3sec).
2196 * As the HDMI core is turned off, the write gets blocked.
2197 * Avoid this by routing audio to speaker until standby.
2198 */
2199 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2200 val == AUDIO_DEVICE_NONE) {
2201 val = AUDIO_DEVICE_OUT_SPEAKER;
2202 }
2203
2204 /*
2205 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002206 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002207 * the select_devices(). But how do we undo this?
2208 *
2209 * For example, music playback is active on headset (deep-buffer usecase)
2210 * and if we go to ringtones and select a ringtone, low-latency usecase
2211 * will be started on headset+speaker. As we can't enable headset+speaker
2212 * and headset devices at the same time, select_devices() switches the music
2213 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2214 * So when the ringtone playback is completed, how do we undo the same?
2215 *
2216 * We are relying on the out_set_parameters() call on deep-buffer output,
2217 * once the ringtone playback is ended.
2218 * NOTE: We should not check if the current devices are same as new devices.
2219 * Because select_devices() must be called to switch back the music
2220 * playback to headset.
2221 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002222 audio_devices_t new_dev = val;
2223 if (new_dev != AUDIO_DEVICE_NONE) {
2224 bool same_dev = out->devices == new_dev;
2225 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002226
Eric Laurenta7657192014-10-09 21:09:33 -07002227 if (output_drives_call(adev, out)) {
2228 if (!voice_is_in_call(adev)) {
2229 if (adev->mode == AUDIO_MODE_IN_CALL) {
2230 adev->current_call_output = out;
2231 ret = voice_start_call(adev);
2232 }
2233 } else {
2234 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002235 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002236 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002237 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002238
2239 if (!out->standby) {
2240 if (!same_dev) {
2241 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002242 // inform adm before actual routing to prevent glitches.
2243 if (adev->adm_on_routing_change) {
2244 adev->adm_on_routing_change(adev->adm_data,
2245 out->handle);
2246 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002247 }
2248 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002249 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002250
2251 // on device switch force swap, lower functions will make sure
2252 // to check if swap is allowed or not.
2253
2254 if (!same_dev)
2255 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002256 }
2257
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002258 }
2259
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002261 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002262
2263 /*handles device and call state changes*/
2264 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002266
2267 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2268 parse_compress_metadata(out, parms);
2269 }
2270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002272 ALOGV("%s: exit: code(%d)", __func__, status);
2273 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274}
2275
Haynes Mathew George569b7482017-05-08 14:44:27 -07002276static bool stream_get_parameter_channels(struct str_parms *query,
2277 struct str_parms *reply,
2278 audio_channel_mask_t *supported_channel_masks) {
2279 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002282 size_t i, j;
2283
2284 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2285 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286 value[0] = '\0';
2287 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002288 while (supported_channel_masks[i] != 0) {
2289 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2290 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002291 if (!first) {
2292 strcat(value, "|");
2293 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002294 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002295 first = false;
2296 break;
2297 }
2298 }
2299 i++;
2300 }
2301 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002302 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002303 return ret >= 0;
2304}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002305
Haynes Mathew George569b7482017-05-08 14:44:27 -07002306static bool stream_get_parameter_formats(struct str_parms *query,
2307 struct str_parms *reply,
2308 audio_format_t *supported_formats) {
2309 int ret = -1;
2310 char value[256];
2311 int i;
2312
2313 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2314 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002315 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002316 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002317 case AUDIO_FORMAT_PCM_16_BIT:
2318 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2319 break;
2320 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2321 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2322 break;
2323 case AUDIO_FORMAT_PCM_32_BIT:
2324 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2325 break;
2326 default:
2327 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002328 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002329 break;
2330 }
2331 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002332 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002333 return ret >= 0;
2334}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002335
Haynes Mathew George569b7482017-05-08 14:44:27 -07002336static bool stream_get_parameter_rates(struct str_parms *query,
2337 struct str_parms *reply,
2338 uint32_t *supported_sample_rates) {
2339
2340 int i;
2341 char value[256];
2342 int ret = -1;
2343 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2344 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002345 value[0] = '\0';
2346 i=0;
2347 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002348 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002349 int avail = sizeof(value) - cursor;
2350 ret = snprintf(value + cursor, avail, "%s%d",
2351 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002352 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002353 if (ret < 0 || ret >= avail) {
2354 // if cursor is at the last element of the array
2355 // overwrite with \0 is duplicate work as
2356 // snprintf already put a \0 in place.
2357 // else
2358 // we had space to write the '|' at value[cursor]
2359 // (which will be overwritten) or no space to fill
2360 // the first element (=> cursor == 0)
2361 value[cursor] = '\0';
2362 break;
2363 }
2364 cursor += ret;
2365 ++i;
2366 }
2367 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2368 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002369 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002370 return ret >= 0;
2371}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002372
Haynes Mathew George569b7482017-05-08 14:44:27 -07002373static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2374{
2375 struct stream_out *out = (struct stream_out *)stream;
2376 struct str_parms *query = str_parms_create_str(keys);
2377 char *str;
2378 struct str_parms *reply = str_parms_create();
2379 bool replied = false;
2380 ALOGV("%s: enter: keys - %s", __func__, keys);
2381
2382 replied |= stream_get_parameter_channels(query, reply,
2383 &out->supported_channel_masks[0]);
2384 replied |= stream_get_parameter_formats(query, reply,
2385 &out->supported_formats[0]);
2386 replied |= stream_get_parameter_rates(query, reply,
2387 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002388 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 str = str_parms_to_str(reply);
2390 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002391 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392 }
2393 str_parms_destroy(query);
2394 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002395 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396 return str;
2397}
2398
2399static uint32_t out_get_latency(const struct audio_stream_out *stream)
2400{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002401 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002402 struct stream_out *out = (struct stream_out *)stream;
2403
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002404 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2405 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002406 else if ((out->realtime) ||
2407 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002408 // since the buffer won't be filled up faster than realtime,
2409 // return a smaller number
2410 period_ms = (out->af_period_multiplier * out->config.period_size *
2411 1000) / (out->config.rate);
2412 hw_delay = platform_render_latency(out->usecase)/1000;
2413 return period_ms + hw_delay;
2414 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002415
2416 return (out->config.period_count * out->config.period_size * 1000) /
2417 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418}
2419
2420static int out_set_volume(struct audio_stream_out *stream, float left,
2421 float right)
2422{
Eric Laurenta9024de2013-04-04 09:19:12 -07002423 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002424 int volume[2];
2425
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002426 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002427 /* only take left channel into account: the API is for stereo anyway */
2428 out->muted = (left == 0.0f);
2429 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002430 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2431 const char *mixer_ctl_name = "Compress Playback Volume";
2432 struct audio_device *adev = out->dev;
2433 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002434 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2435 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002436 /* try with the control based on device id */
2437 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2438 PCM_PLAYBACK);
2439 char ctl_name[128] = {0};
2440 snprintf(ctl_name, sizeof(ctl_name),
2441 "Compress Playback %d Volume", pcm_device_id);
2442 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2443 if (!ctl) {
2444 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2445 return -EINVAL;
2446 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002447 }
2448 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2449 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2450 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2451 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002452 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002453 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2454 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2455 if (!out->standby) {
2456 // if in standby, cached volume will be sent after stream is opened
2457 audio_extn_utils_send_app_type_gain(out->dev,
2458 out->app_type_cfg.app_type,
2459 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002460 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002461 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002462 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464 return -ENOSYS;
2465}
2466
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002467// note: this call is safe only if the stream_cb is
2468// removed first in close_output_stream (as is done now).
2469static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2470{
2471 if (!stream || !parms)
2472 return;
2473
2474 struct stream_out *out = (struct stream_out *)stream;
2475 struct audio_device *adev = out->dev;
2476
2477 card_status_t status;
2478 int card;
2479 if (parse_snd_card_status(parms, &card, &status) < 0)
2480 return;
2481
2482 pthread_mutex_lock(&adev->lock);
2483 bool valid_cb = (card == adev->snd_card);
2484 pthread_mutex_unlock(&adev->lock);
2485
2486 if (!valid_cb)
2487 return;
2488
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002489 lock_output_stream(out);
2490 if (out->card_status != status)
2491 out->card_status = status;
2492 pthread_mutex_unlock(&out->lock);
2493
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002494 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2495 use_case_table[out->usecase],
2496 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2497
2498 if (status == CARD_STATUS_OFFLINE)
2499 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002500
2501 return;
2502}
2503
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002504#ifdef NO_AUDIO_OUT
2505static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002506 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002507{
2508 struct stream_out *out = (struct stream_out *)stream;
2509
2510 /* No Output device supported other than BT for playback.
2511 * Sleep for the amount of buffer duration
2512 */
Eric Laurenta1478072015-09-21 17:21:52 -07002513 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002514 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2515 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002516 out_get_sample_rate(&out->stream.common));
2517 pthread_mutex_unlock(&out->lock);
2518 return bytes;
2519}
2520#endif
2521
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2523 size_t bytes)
2524{
2525 struct stream_out *out = (struct stream_out *)stream;
2526 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002527 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002528 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529
Eric Laurenta1478072015-09-21 17:21:52 -07002530 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002531 // this is always nonzero
Andy Hung928efbe2017-06-12 14:05:22 -07002532 const size_t frame_size = audio_stream_out_frame_size(stream);
2533 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002534
Eric Laurent0e46adf2016-12-16 12:49:24 -08002535 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2536 error_code = ERROR_CODE_WRITE;
2537 goto exit;
2538 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002540 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002541 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002543 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002544 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002546 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 goto exit;
2548 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002549
2550 if (last_known_cal_step != -1) {
2551 ALOGD("%s: retry previous failed cal level set", __func__);
2552 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2553 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002556 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002557 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002558 if (out->send_new_metadata) {
2559 ALOGVV("send new gapless metadata");
2560 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2561 out->send_new_metadata = 0;
2562 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002563 unsigned int avail;
2564 struct timespec tstamp;
2565 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2566 /* Do not limit write size if the available frames count is unknown */
2567 if (ret != 0) {
2568 avail = bytes;
2569 }
2570 if (avail == 0) {
2571 ret = 0;
2572 } else {
2573 if (avail > bytes) {
2574 avail = bytes;
2575 }
2576 ret = compress_write(out->compr, buffer, avail);
2577 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2578 __func__, avail, ret);
2579 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002580
Eric Laurent6e895242013-09-05 16:10:57 -07002581 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002582 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2583 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002584 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002585 compress_start(out->compr);
2586 out->playback_started = 1;
2587 out->offload_state = OFFLOAD_STATE_PLAYING;
2588 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002589 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002590 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002591 } else {
2592 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002593 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002594 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002595 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002596 return ret;
2597 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002598 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002599 if (out->pcm) {
2600 if (out->muted)
2601 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002602
Eric Laurent0e46adf2016-12-16 12:49:24 -08002603 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002604
Haynes Mathew George03c40102016-01-29 17:57:48 -08002605 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2606 out->config.rate;
2607 request_out_focus(out, ns);
2608
2609 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2610 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002611 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002612 else
2613 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002614
Haynes Mathew George03c40102016-01-29 17:57:48 -08002615 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002616 } else {
2617 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002618 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619 }
2620
2621exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002622 // For PCM we always consume the buffer and return #bytes regardless of ret.
2623 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung928efbe2017-06-12 14:05:22 -07002624 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002625 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002626 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002627
2628 // only get time if needed for logging, as it is a system call on 32 bit devices.
2629 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2630 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2631 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002632
Andy Hung7401c7c2016-09-21 12:41:21 -07002633 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002634 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002635 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2636 ALOGE_IF(out->pcm != NULL,
2637 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung928efbe2017-06-12 14:05:22 -07002638 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002639 // usleep not guaranteed for values over 1 second but we don't limit here.
2640 }
2641 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 pthread_mutex_unlock(&out->lock);
2644
2645 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002646 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002647 if (sleeptime_us != 0)
2648 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002649 } else {
2650 // only log if the data is properly written (out->power_log may be null)
Andy Hung928efbe2017-06-12 14:05:22 -07002651 power_log_log(out->power_log, buffer, frames, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 }
2653 return bytes;
2654}
2655
2656static int out_get_render_position(const struct audio_stream_out *stream,
2657 uint32_t *dsp_frames)
2658{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002659 struct stream_out *out = (struct stream_out *)stream;
2660 *dsp_frames = 0;
2661 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002662 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002663 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002664 unsigned long frames = 0;
2665 // TODO: check return value
2666 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2667 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002668 ALOGVV("%s rendered frames %d sample_rate %d",
2669 __func__, *dsp_frames, out->sample_rate);
2670 }
2671 pthread_mutex_unlock(&out->lock);
2672 return 0;
2673 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002674 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675}
2676
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002677static int out_add_audio_effect(const struct audio_stream *stream __unused,
2678 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679{
2680 return 0;
2681}
2682
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002683static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2684 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685{
2686 return 0;
2687}
2688
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002689static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2690 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002692 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002693}
2694
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002695static int out_get_presentation_position(const struct audio_stream_out *stream,
2696 uint64_t *frames, struct timespec *timestamp)
2697{
2698 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002699 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002700 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002701
Eric Laurenta1478072015-09-21 17:21:52 -07002702 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002703
Eric Laurent949a0892013-09-20 09:20:13 -07002704 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2705 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002706 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002707 compress_get_tstamp(out->compr, &dsp_frames,
2708 &out->sample_rate);
2709 ALOGVV("%s rendered frames %ld sample_rate %d",
2710 __func__, dsp_frames, out->sample_rate);
2711 *frames = dsp_frames;
2712 ret = 0;
2713 /* this is the best we can do */
2714 clock_gettime(CLOCK_MONOTONIC, timestamp);
2715 }
2716 } else {
2717 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002718 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002719 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2720 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002721 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002722 // This adjustment accounts for buffering after app processor.
2723 // It is based on estimated DSP latency per use case, rather than exact.
2724 signed_frames -=
2725 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2726
Eric Laurent949a0892013-09-20 09:20:13 -07002727 // It would be unusual for this value to be negative, but check just in case ...
2728 if (signed_frames >= 0) {
2729 *frames = signed_frames;
2730 ret = 0;
2731 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002732 }
2733 }
2734 }
2735
2736 pthread_mutex_unlock(&out->lock);
2737
2738 return ret;
2739}
2740
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002741static int out_set_callback(struct audio_stream_out *stream,
2742 stream_callback_t callback, void *cookie)
2743{
2744 struct stream_out *out = (struct stream_out *)stream;
2745
2746 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002747 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002748 out->offload_callback = callback;
2749 out->offload_cookie = cookie;
2750 pthread_mutex_unlock(&out->lock);
2751 return 0;
2752}
2753
2754static int out_pause(struct audio_stream_out* stream)
2755{
2756 struct stream_out *out = (struct stream_out *)stream;
2757 int status = -ENOSYS;
2758 ALOGV("%s", __func__);
2759 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002760 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002761 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2762 status = compress_pause(out->compr);
2763 out->offload_state = OFFLOAD_STATE_PAUSED;
2764 }
2765 pthread_mutex_unlock(&out->lock);
2766 }
2767 return status;
2768}
2769
2770static int out_resume(struct audio_stream_out* stream)
2771{
2772 struct stream_out *out = (struct stream_out *)stream;
2773 int status = -ENOSYS;
2774 ALOGV("%s", __func__);
2775 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2776 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002777 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002778 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2779 status = compress_resume(out->compr);
2780 out->offload_state = OFFLOAD_STATE_PLAYING;
2781 }
2782 pthread_mutex_unlock(&out->lock);
2783 }
2784 return status;
2785}
2786
2787static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2788{
2789 struct stream_out *out = (struct stream_out *)stream;
2790 int status = -ENOSYS;
2791 ALOGV("%s", __func__);
2792 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002793 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002794 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2795 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2796 else
2797 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2798 pthread_mutex_unlock(&out->lock);
2799 }
2800 return status;
2801}
2802
2803static int out_flush(struct audio_stream_out* stream)
2804{
2805 struct stream_out *out = (struct stream_out *)stream;
2806 ALOGV("%s", __func__);
2807 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002808 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002809 stop_compressed_output_l(out);
2810 pthread_mutex_unlock(&out->lock);
2811 return 0;
2812 }
2813 return -ENOSYS;
2814}
2815
Eric Laurent0e46adf2016-12-16 12:49:24 -08002816static int out_stop(const struct audio_stream_out* stream)
2817{
2818 struct stream_out *out = (struct stream_out *)stream;
2819 struct audio_device *adev = out->dev;
2820 int ret = -ENOSYS;
2821
2822 ALOGV("%s", __func__);
2823 pthread_mutex_lock(&adev->lock);
2824 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2825 out->playback_started && out->pcm != NULL) {
2826 pcm_stop(out->pcm);
2827 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002828 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002829 }
2830 pthread_mutex_unlock(&adev->lock);
2831 return ret;
2832}
2833
2834static int out_start(const struct audio_stream_out* stream)
2835{
2836 struct stream_out *out = (struct stream_out *)stream;
2837 struct audio_device *adev = out->dev;
2838 int ret = -ENOSYS;
2839
2840 ALOGV("%s", __func__);
2841 pthread_mutex_lock(&adev->lock);
2842 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2843 !out->playback_started && out->pcm != NULL) {
2844 ret = start_output_stream(out);
2845 if (ret == 0) {
2846 out->playback_started = true;
2847 }
2848 }
2849 pthread_mutex_unlock(&adev->lock);
2850 return ret;
2851}
2852
Phil Burkbc991042017-02-24 08:06:44 -08002853/*
2854 * Modify config->period_count based on min_size_frames
2855 */
2856static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2857{
2858 int periodCountRequested = (min_size_frames + config->period_size - 1)
2859 / config->period_size;
2860 int periodCount = MMAP_PERIOD_COUNT_MIN;
2861
2862 ALOGV("%s original config.period_size = %d config.period_count = %d",
2863 __func__, config->period_size, config->period_count);
2864
2865 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2866 periodCount *= 2;
2867 }
2868 config->period_count = periodCount;
2869
2870 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2871}
2872
Eric Laurent0e46adf2016-12-16 12:49:24 -08002873static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2874 int32_t min_size_frames,
2875 struct audio_mmap_buffer_info *info)
2876{
2877 struct stream_out *out = (struct stream_out *)stream;
2878 struct audio_device *adev = out->dev;
2879 int ret = 0;
2880 unsigned int offset1;
2881 unsigned int frames1;
2882 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002883 uint32_t mmap_size;
2884 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002885
2886 ALOGV("%s", __func__);
2887 pthread_mutex_lock(&adev->lock);
2888
2889 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002890 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002891 ret = -EINVAL;
2892 goto exit;
2893 }
2894 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002895 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002896 ret = -ENOSYS;
2897 goto exit;
2898 }
2899 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2900 if (out->pcm_device_id < 0) {
2901 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2902 __func__, out->pcm_device_id, out->usecase);
2903 ret = -EINVAL;
2904 goto exit;
2905 }
Phil Burkbc991042017-02-24 08:06:44 -08002906
2907 adjust_mmap_period_count(&out->config, min_size_frames);
2908
Eric Laurent0e46adf2016-12-16 12:49:24 -08002909 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2910 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2911 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2912 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2913 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2914 step = "open";
2915 ret = -ENODEV;
2916 goto exit;
2917 }
2918 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2919 if (ret < 0) {
2920 step = "begin";
2921 goto exit;
2922 }
2923 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002924 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002925 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002926 ret = platform_get_mmap_data_fd(adev->platform,
2927 out->pcm_device_id, 0 /*playback*/,
2928 &info->shared_memory_fd,
2929 &mmap_size);
2930 if (ret < 0) {
2931 // Fall back to non exclusive mode
2932 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2933 } else {
2934 if (mmap_size < buffer_size) {
2935 step = "mmap";
2936 goto exit;
2937 }
2938 // FIXME: indicate exclusive mode support by returning a negative buffer size
2939 info->buffer_size_frames *= -1;
2940 }
2941 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002942
2943 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2944 if (ret < 0) {
2945 step = "commit";
2946 goto exit;
2947 }
Phil Burkbc991042017-02-24 08:06:44 -08002948
2949 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002950 ret = 0;
2951
2952 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2953 __func__, info->shared_memory_address, info->buffer_size_frames);
2954
2955exit:
2956 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002957 if (out->pcm == NULL) {
2958 ALOGE("%s: %s - %d", __func__, step, ret);
2959 } else {
2960 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002961 pcm_close(out->pcm);
2962 out->pcm = NULL;
2963 }
2964 }
2965 pthread_mutex_unlock(&adev->lock);
2966 return ret;
2967}
2968
2969static int out_get_mmap_position(const struct audio_stream_out *stream,
2970 struct audio_mmap_position *position)
2971{
2972 struct stream_out *out = (struct stream_out *)stream;
2973 ALOGVV("%s", __func__);
2974 if (position == NULL) {
2975 return -EINVAL;
2976 }
2977 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2978 return -ENOSYS;
2979 }
2980 if (out->pcm == NULL) {
2981 return -ENOSYS;
2982 }
2983
2984 struct timespec ts = { 0, 0 };
2985 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2986 if (ret < 0) {
2987 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2988 return ret;
2989 }
Andy Hungfc044e12017-03-20 09:24:22 -07002990 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002991 return 0;
2992}
2993
2994
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995/** audio_stream_in implementation **/
2996static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2997{
2998 struct stream_in *in = (struct stream_in *)stream;
2999
3000 return in->config.rate;
3001}
3002
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003003static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003004{
3005 return -ENOSYS;
3006}
3007
3008static size_t in_get_buffer_size(const struct audio_stream *stream)
3009{
3010 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003011 return in->config.period_size * in->af_period_multiplier *
3012 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013}
3014
3015static uint32_t in_get_channels(const struct audio_stream *stream)
3016{
3017 struct stream_in *in = (struct stream_in *)stream;
3018
3019 return in->channel_mask;
3020}
3021
vivek mehta4ed66e62016-04-15 23:33:34 -07003022static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023{
vivek mehta4ed66e62016-04-15 23:33:34 -07003024 struct stream_in *in = (struct stream_in *)stream;
3025 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026}
3027
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003028static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029{
3030 return -ENOSYS;
3031}
3032
3033static int in_standby(struct audio_stream *stream)
3034{
3035 struct stream_in *in = (struct stream_in *)stream;
3036 struct audio_device *adev = in->dev;
3037 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003038 bool do_stop = true;
3039
Eric Laurent994a6932013-07-17 11:51:42 -07003040 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003041
3042 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003043
3044 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003045 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003046 audio_extn_sound_trigger_stop_lab(in);
3047 in->standby = true;
3048 }
3049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003051 if (adev->adm_deregister_stream)
3052 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3053
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003054 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003056 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003057 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003058 in->capture_started = false;
3059 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003060 if (in->pcm) {
3061 pcm_close(in->pcm);
3062 in->pcm = NULL;
3063 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003064 adev->enable_voicerx = false;
3065 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003066 if (do_stop) {
3067 status = stop_input_stream(in);
3068 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003069 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070 }
3071 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003072 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003073 return status;
3074}
3075
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003076static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077{
3078 return 0;
3079}
3080
3081static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3082{
3083 struct stream_in *in = (struct stream_in *)stream;
3084 struct audio_device *adev = in->dev;
3085 struct str_parms *parms;
3086 char *str;
3087 char value[32];
3088 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003089 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003090
Eric Laurent994a6932013-07-17 11:51:42 -07003091 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 parms = str_parms_create_str(kvpairs);
3093
3094 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3095
Eric Laurenta1478072015-09-21 17:21:52 -07003096 lock_input_stream(in);
3097
Eric Laurent150dbfe2013-02-27 14:31:02 -08003098 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 if (ret >= 0) {
3100 val = atoi(value);
3101 /* no audio source uses val == 0 */
3102 if ((in->source != val) && (val != 0)) {
3103 in->source = val;
3104 }
3105 }
3106
3107 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003108
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003109 if (ret >= 0) {
3110 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003111 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112 in->device = val;
3113 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003114 if (!in->standby) {
3115 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003116 // inform adm before actual routing to prevent glitches.
3117 if (adev->adm_on_routing_change) {
3118 adev->adm_on_routing_change(adev->adm_data,
3119 in->capture_handle);
3120 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003121 select_devices(adev, in->usecase);
3122 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123 }
3124 }
3125
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003127 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128
3129 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003130 ALOGV("%s: exit: status(%d)", __func__, status);
3131 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132}
3133
Haynes Mathew George569b7482017-05-08 14:44:27 -07003134static char* in_get_parameters(const struct audio_stream *stream,
3135 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003136{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003137 struct stream_in *in = (struct stream_in *)stream;
3138 struct str_parms *query = str_parms_create_str(keys);
3139 char *str;
3140 struct str_parms *reply = str_parms_create();
3141 bool replied = false;
3142
3143 ALOGV("%s: enter: keys - %s", __func__, keys);
3144 replied |= stream_get_parameter_channels(query, reply,
3145 &in->supported_channel_masks[0]);
3146 replied |= stream_get_parameter_formats(query, reply,
3147 &in->supported_formats[0]);
3148 replied |= stream_get_parameter_rates(query, reply,
3149 &in->supported_sample_rates[0]);
3150 if (replied) {
3151 str = str_parms_to_str(reply);
3152 } else {
3153 str = strdup(keys);
3154 }
3155 str_parms_destroy(query);
3156 str_parms_destroy(reply);
3157 ALOGV("%s: exit: returns - %s", __func__, str);
3158 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159}
3160
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003161static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003163 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164}
3165
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003166static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3167{
3168 if (!stream || !parms)
3169 return;
3170
3171 struct stream_in *in = (struct stream_in *)stream;
3172 struct audio_device *adev = in->dev;
3173
3174 card_status_t status;
3175 int card;
3176 if (parse_snd_card_status(parms, &card, &status) < 0)
3177 return;
3178
3179 pthread_mutex_lock(&adev->lock);
3180 bool valid_cb = (card == adev->snd_card);
3181 pthread_mutex_unlock(&adev->lock);
3182
3183 if (!valid_cb)
3184 return;
3185
3186 lock_input_stream(in);
3187 if (in->card_status != status)
3188 in->card_status = status;
3189 pthread_mutex_unlock(&in->lock);
3190
3191 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3192 use_case_table[in->usecase],
3193 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3194
3195 // a better solution would be to report error back to AF and let
3196 // it put the stream to standby
3197 if (status == CARD_STATUS_OFFLINE)
3198 in_standby(&in->stream.common);
3199
3200 return;
3201}
3202
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3204 size_t bytes)
3205{
3206 struct stream_in *in = (struct stream_in *)stream;
3207 struct audio_device *adev = in->dev;
3208 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003209 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210
Eric Laurenta1478072015-09-21 17:21:52 -07003211 lock_input_stream(in);
Andy Hung928efbe2017-06-12 14:05:22 -07003212 const size_t frame_size = audio_stream_in_frame_size(stream);
3213 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003214
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003215 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003216 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003217 /* Read from sound trigger HAL */
3218 audio_extn_sound_trigger_read(in, buffer, bytes);
3219 pthread_mutex_unlock(&in->lock);
3220 return bytes;
3221 }
3222
Eric Laurent0e46adf2016-12-16 12:49:24 -08003223 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3224 ret = -ENOSYS;
3225 goto exit;
3226 }
3227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003229 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003231 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 goto exit;
3234 }
3235 in->standby = 0;
3236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237
Haynes Mathew George03c40102016-01-29 17:57:48 -08003238 //what's the duration requested by the client?
3239 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3240 in->config.rate;
3241 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003242
Haynes Mathew George03c40102016-01-29 17:57:48 -08003243 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003244 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003245 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003246 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003247 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003248 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003249 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003250 if (ret < 0) {
3251 ALOGE("Failed to read w/err %s", strerror(errno));
3252 ret = -errno;
3253 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003254 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3255 if (bytes % 4 == 0) {
3256 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3257 int_buf_stream = buffer;
3258 for (size_t itt=0; itt < bytes/4 ; itt++) {
3259 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003260 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003261 } else {
3262 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3263 ret = -EINVAL;
3264 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003265 }
3266 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 }
3268
Haynes Mathew George03c40102016-01-29 17:57:48 -08003269 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 /*
3272 * Instead of writing zeroes here, we could trust the hardware
3273 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003274 * 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 -08003275 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003276 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277 memset(buffer, 0, bytes);
3278
3279exit:
3280 pthread_mutex_unlock(&in->lock);
3281
3282 if (ret != 0) {
3283 in_standby(&in->stream.common);
3284 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung928efbe2017-06-12 14:05:22 -07003285 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003286 memset(buffer, 0, bytes); // clear return data
3287 }
3288 if (bytes > 0) {
Andy Hung928efbe2017-06-12 14:05:22 -07003289 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003290 }
3291 return bytes;
3292}
3293
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003294static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295{
3296 return 0;
3297}
3298
Andy Hung6ebe5962016-01-15 17:46:57 -08003299static int in_get_capture_position(const struct audio_stream_in *stream,
3300 int64_t *frames, int64_t *time)
3301{
3302 if (stream == NULL || frames == NULL || time == NULL) {
3303 return -EINVAL;
3304 }
3305 struct stream_in *in = (struct stream_in *)stream;
3306 int ret = -ENOSYS;
3307
3308 lock_input_stream(in);
3309 if (in->pcm) {
3310 struct timespec timestamp;
3311 unsigned int avail;
3312 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3313 *frames = in->frames_read + avail;
3314 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3315 ret = 0;
3316 }
3317 }
3318 pthread_mutex_unlock(&in->lock);
3319 return ret;
3320}
3321
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003322static int add_remove_audio_effect(const struct audio_stream *stream,
3323 effect_handle_t effect,
3324 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003326 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003327 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003328 int status = 0;
3329 effect_descriptor_t desc;
3330
3331 status = (*effect)->get_descriptor(effect, &desc);
3332 if (status != 0)
3333 return status;
3334
Eric Laurenta1478072015-09-21 17:21:52 -07003335 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003336 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003337 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003338 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003339 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003340 in->enable_aec != enable &&
3341 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3342 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003343 if (!enable)
3344 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003345 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3346 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3347 adev->enable_voicerx = enable;
3348 struct audio_usecase *usecase;
3349 struct listnode *node;
3350 list_for_each(node, &adev->usecase_list) {
3351 usecase = node_to_item(node, struct audio_usecase, list);
3352 if (usecase->type == PCM_PLAYBACK) {
3353 select_devices(adev, usecase->id);
3354 break;
3355 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003356 }
3357 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003358 if (!in->standby)
3359 select_devices(in->dev, in->usecase);
3360 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003361 if (in->enable_ns != enable &&
3362 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3363 in->enable_ns = enable;
3364 if (!in->standby)
3365 select_devices(in->dev, in->usecase);
3366 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003367 pthread_mutex_unlock(&in->dev->lock);
3368 pthread_mutex_unlock(&in->lock);
3369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 return 0;
3371}
3372
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003373static int in_add_audio_effect(const struct audio_stream *stream,
3374 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375{
Eric Laurent994a6932013-07-17 11:51:42 -07003376 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003377 return add_remove_audio_effect(stream, effect, true);
3378}
3379
3380static int in_remove_audio_effect(const struct audio_stream *stream,
3381 effect_handle_t effect)
3382{
Eric Laurent994a6932013-07-17 11:51:42 -07003383 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003384 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385}
3386
Eric Laurent0e46adf2016-12-16 12:49:24 -08003387static int in_stop(const struct audio_stream_in* stream)
3388{
3389 struct stream_in *in = (struct stream_in *)stream;
3390 struct audio_device *adev = in->dev;
3391
3392 int ret = -ENOSYS;
3393 ALOGV("%s", __func__);
3394 pthread_mutex_lock(&adev->lock);
3395 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3396 in->capture_started && in->pcm != NULL) {
3397 pcm_stop(in->pcm);
3398 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003399 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003400 }
3401 pthread_mutex_unlock(&adev->lock);
3402 return ret;
3403}
3404
3405static int in_start(const struct audio_stream_in* stream)
3406{
3407 struct stream_in *in = (struct stream_in *)stream;
3408 struct audio_device *adev = in->dev;
3409 int ret = -ENOSYS;
3410
3411 ALOGV("%s in %p", __func__, in);
3412 pthread_mutex_lock(&adev->lock);
3413 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3414 !in->capture_started && in->pcm != NULL) {
3415 if (!in->capture_started) {
3416 ret = start_input_stream(in);
3417 if (ret == 0) {
3418 in->capture_started = true;
3419 }
3420 }
3421 }
3422 pthread_mutex_unlock(&adev->lock);
3423 return ret;
3424}
3425
3426static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3427 int32_t min_size_frames,
3428 struct audio_mmap_buffer_info *info)
3429{
3430 struct stream_in *in = (struct stream_in *)stream;
3431 struct audio_device *adev = in->dev;
3432 int ret = 0;
3433 unsigned int offset1;
3434 unsigned int frames1;
3435 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003436 uint32_t mmap_size;
3437 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003438
3439 pthread_mutex_lock(&adev->lock);
3440 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003441
Eric Laurent0e46adf2016-12-16 12:49:24 -08003442 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003443 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003444 ret = -EINVAL;
3445 goto exit;
3446 }
3447 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003448 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003449 ALOGV("%s in %p", __func__, in);
3450 ret = -ENOSYS;
3451 goto exit;
3452 }
3453 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3454 if (in->pcm_device_id < 0) {
3455 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3456 __func__, in->pcm_device_id, in->usecase);
3457 ret = -EINVAL;
3458 goto exit;
3459 }
Phil Burkbc991042017-02-24 08:06:44 -08003460
3461 adjust_mmap_period_count(&in->config, min_size_frames);
3462
Eric Laurent0e46adf2016-12-16 12:49:24 -08003463 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3464 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3465 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3466 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3467 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3468 step = "open";
3469 ret = -ENODEV;
3470 goto exit;
3471 }
3472
3473 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3474 if (ret < 0) {
3475 step = "begin";
3476 goto exit;
3477 }
3478 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003479 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003480 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003481 ret = platform_get_mmap_data_fd(adev->platform,
3482 in->pcm_device_id, 1 /*capture*/,
3483 &info->shared_memory_fd,
3484 &mmap_size);
3485 if (ret < 0) {
3486 // Fall back to non exclusive mode
3487 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3488 } else {
3489 if (mmap_size < buffer_size) {
3490 step = "mmap";
3491 goto exit;
3492 }
3493 // FIXME: indicate exclusive mode support by returning a negative buffer size
3494 info->buffer_size_frames *= -1;
3495 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003496
Haynes Mathew George96483a22017-03-28 14:52:47 -07003497 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003498
3499 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3500 if (ret < 0) {
3501 step = "commit";
3502 goto exit;
3503 }
3504
Phil Burkbc991042017-02-24 08:06:44 -08003505 in->standby = false;
3506 ret = 0;
3507
Eric Laurent0e46adf2016-12-16 12:49:24 -08003508 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3509 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003510
3511exit:
3512 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003513 if (in->pcm == NULL) {
3514 ALOGE("%s: %s - %d", __func__, step, ret);
3515 } else {
3516 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003517 pcm_close(in->pcm);
3518 in->pcm = NULL;
3519 }
3520 }
3521 pthread_mutex_unlock(&adev->lock);
3522 return ret;
3523}
3524
3525static int in_get_mmap_position(const struct audio_stream_in *stream,
3526 struct audio_mmap_position *position)
3527{
3528 struct stream_in *in = (struct stream_in *)stream;
3529 ALOGVV("%s", __func__);
3530 if (position == NULL) {
3531 return -EINVAL;
3532 }
3533 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3534 return -ENOSYS;
3535 }
3536 if (in->pcm == NULL) {
3537 return -ENOSYS;
3538 }
3539 struct timespec ts = { 0, 0 };
3540 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3541 if (ret < 0) {
3542 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3543 return ret;
3544 }
Andy Hungfc044e12017-03-20 09:24:22 -07003545 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003546 return 0;
3547}
3548
3549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003550static int adev_open_output_stream(struct audio_hw_device *dev,
3551 audio_io_handle_t handle,
3552 audio_devices_t devices,
3553 audio_output_flags_t flags,
3554 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003555 struct audio_stream_out **stream_out,
3556 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557{
3558 struct audio_device *adev = (struct audio_device *)dev;
3559 struct stream_out *out;
3560 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003561 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3562 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3563 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3564 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003565
Eric Laurent994a6932013-07-17 11:51:42 -07003566 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 __func__, config->sample_rate, config->channel_mask, devices, flags);
3568 *stream_out = NULL;
3569 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3570
3571 if (devices == AUDIO_DEVICE_NONE)
3572 devices = AUDIO_DEVICE_OUT_SPEAKER;
3573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 out->flags = flags;
3575 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003576 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003577 out->format = config->format;
3578 out->sample_rate = config->sample_rate;
3579 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3580 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003581 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003582
3583 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003584 if (audio_is_linear_pcm(out->format) &&
3585 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003586 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003587 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003588 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003589 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003590 if (config->sample_rate == 0)
3591 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3592 if (config->channel_mask == 0)
3593 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3594 if (config->format == AUDIO_FORMAT_DEFAULT)
3595 config->format = AUDIO_FORMAT_PCM_16_BIT;
3596 } else if (is_usb_dev) {
3597 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3598 &config->format,
3599 &out->supported_formats[0],
3600 MAX_SUPPORTED_FORMATS,
3601 &config->channel_mask,
3602 &out->supported_channel_masks[0],
3603 MAX_SUPPORTED_CHANNEL_MASKS,
3604 &config->sample_rate,
3605 &out->supported_sample_rates[0],
3606 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003607 ALOGV("plugged dev USB ret %d", ret);
3608 } else {
3609 ret = -1;
3610 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003611 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003612 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003613 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003614
Haynes Mathew George569b7482017-05-08 14:44:27 -07003615 out->channel_mask = config->channel_mask;
3616 out->sample_rate = config->sample_rate;
3617 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003618 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3619 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003620 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003622 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003623 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3624 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003625 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003626 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003627 pthread_mutex_lock(&adev->lock);
3628 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3629 pthread_mutex_unlock(&adev->lock);
3630
3631 // reject offload during card offline to allow
3632 // fallback to s/w paths
3633 if (offline) {
3634 ret = -ENODEV;
3635 goto error_open;
3636 }
3637
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003638 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3639 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3640 ALOGE("%s: Unsupported Offload information", __func__);
3641 ret = -EINVAL;
3642 goto error_open;
3643 }
3644 if (!is_supported_format(config->offload_info.format)) {
3645 ALOGE("%s: Unsupported audio format", __func__);
3646 ret = -EINVAL;
3647 goto error_open;
3648 }
3649
3650 out->compr_config.codec = (struct snd_codec *)
3651 calloc(1, sizeof(struct snd_codec));
3652
3653 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3654 if (config->offload_info.channel_mask)
3655 out->channel_mask = config->offload_info.channel_mask;
3656 else if (config->channel_mask)
3657 out->channel_mask = config->channel_mask;
3658 out->format = config->offload_info.format;
3659 out->sample_rate = config->offload_info.sample_rate;
3660
3661 out->stream.set_callback = out_set_callback;
3662 out->stream.pause = out_pause;
3663 out->stream.resume = out_resume;
3664 out->stream.drain = out_drain;
3665 out->stream.flush = out_flush;
3666
3667 out->compr_config.codec->id =
3668 get_snd_codec_id(config->offload_info.format);
3669 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3670 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003671 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672 out->compr_config.codec->bit_rate =
3673 config->offload_info.bit_rate;
3674 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003675 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003676 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3677
3678 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3679 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003680
3681 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003682 create_offload_callback_thread(out);
3683 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3684 __func__, config->offload_info.version,
3685 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003686 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003687 switch (config->sample_rate) {
3688 case 8000:
3689 case 16000:
3690 case 48000:
3691 out->sample_rate = config->sample_rate;
3692 break;
3693 default:
3694 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003695 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003696 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003697 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3698 out->config = pcm_config_afe_proxy_playback;
3699 adev->voice_tx_output = out;
David Lin6b00c232017-07-26 00:20:16 -07003700 } else if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3701 AUDIO_OUTPUT_FLAG_VOIP_RX)) {
vivek mehtaa68fea62017-06-08 19:04:02 -07003702 uint32_t buffer_size, frame_size;
3703 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3704 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3705 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3706 out->config = pcm_config_voip;
3707 out->config.format = pcm_format_from_audio_format(config->format);
3708 out->config.rate = config->sample_rate;
3709 out->config.channels =
3710 audio_channel_count_from_out_mask(config->channel_mask);
3711 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3712 config->sample_rate,
3713 config->format,
3714 out->config.channels,
3715 false /*is_low_latency*/);
3716 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3717 out->config.period_size = buffer_size / frame_size;
3718 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3719 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003721 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3722 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3723 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003724 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3725 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3726 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003727 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3728 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003729 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003730 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003731 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3732 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3733 out->config = pcm_config_mmap_playback;
3734 out->stream.start = out_start;
3735 out->stream.stop = out_stop;
3736 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3737 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003738 } else {
3739 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3740 out->config = pcm_config_low_latency;
3741 }
3742 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003743 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003744 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003745 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003747
3748 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3749 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3750 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3751 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3752 __func__, config->sample_rate, config->format, config->channel_mask);
3753 config->sample_rate = out->sample_rate;
3754 config->format = out->format;
3755 config->channel_mask = out->channel_mask;
3756 ret = -EINVAL;
3757 goto error_open;
3758 }
3759
Andy Hung6fcba9c2014-03-18 11:53:32 -07003760 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3761 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003762
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003763 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003764 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003765 adev->primary_output = out;
3766 else {
3767 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003768 ret = -EEXIST;
3769 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003770 }
3771 }
3772
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773 /* Check if this usecase is already existing */
3774 pthread_mutex_lock(&adev->lock);
3775 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3776 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003778 ret = -EEXIST;
3779 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 }
3781 pthread_mutex_unlock(&adev->lock);
3782
3783 out->stream.common.get_sample_rate = out_get_sample_rate;
3784 out->stream.common.set_sample_rate = out_set_sample_rate;
3785 out->stream.common.get_buffer_size = out_get_buffer_size;
3786 out->stream.common.get_channels = out_get_channels;
3787 out->stream.common.get_format = out_get_format;
3788 out->stream.common.set_format = out_set_format;
3789 out->stream.common.standby = out_standby;
3790 out->stream.common.dump = out_dump;
3791 out->stream.common.set_parameters = out_set_parameters;
3792 out->stream.common.get_parameters = out_get_parameters;
3793 out->stream.common.add_audio_effect = out_add_audio_effect;
3794 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3795 out->stream.get_latency = out_get_latency;
3796 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003797#ifdef NO_AUDIO_OUT
3798 out->stream.write = out_write_for_no_output;
3799#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003801#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 out->stream.get_render_position = out_get_render_position;
3803 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003804 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
Eric Laurent0e46adf2016-12-16 12:49:24 -08003806 if (out->realtime)
3807 out->af_period_multiplier = af_period_multiplier;
3808 else
3809 out->af_period_multiplier = 1;
3810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003812 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003813 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003815 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003816 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003817 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819 config->format = out->stream.common.get_format(&out->stream.common);
3820 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3821 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3822
Andy Hunga452b0a2017-03-15 14:51:15 -07003823 out->error_log = error_log_create(
3824 ERROR_LOG_ENTRIES,
3825 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3826
Andy Hungfc044e12017-03-20 09:24:22 -07003827 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003828 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003829 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003830 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3831 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3832
3833 out->power_log = power_log_create(
3834 config->sample_rate,
3835 audio_channel_count_from_out_mask(config->channel_mask),
3836 config->format,
3837 POWER_LOG_ENTRIES,
3838 POWER_LOG_FRAMES_PER_ENTRY);
3839 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003840
3841 /*
3842 By locking output stream before registering, we allow the callback
3843 to update stream's state only after stream's initial state is set to
3844 adev state.
3845 */
3846 lock_output_stream(out);
3847 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3848 pthread_mutex_lock(&adev->lock);
3849 out->card_status = adev->card_status;
3850 pthread_mutex_unlock(&adev->lock);
3851 pthread_mutex_unlock(&out->lock);
3852
vivek mehta4a824772017-06-08 19:05:49 -07003853 stream_app_type_cfg_init(&out->app_type_cfg);
3854
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003856
Eric Laurent994a6932013-07-17 11:51:42 -07003857 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003859
3860error_open:
3861 free(out);
3862 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003863 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003864 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865}
3866
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003867static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003868 struct audio_stream_out *stream)
3869{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003870 struct stream_out *out = (struct stream_out *)stream;
3871 struct audio_device *adev = out->dev;
3872
Eric Laurent994a6932013-07-17 11:51:42 -07003873 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003874
3875 // must deregister from sndmonitor first to prevent races
3876 // between the callback and close_stream
3877 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003879 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3880 destroy_offload_callback_thread(out);
3881
3882 if (out->compr_config.codec != NULL)
3883 free(out->compr_config.codec);
3884 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003885
3886 if (adev->voice_tx_output == out)
3887 adev->voice_tx_output = NULL;
3888
Andy Hungfc044e12017-03-20 09:24:22 -07003889 power_log_destroy(out->power_log);
3890 out->power_log = NULL;
3891
Andy Hunga452b0a2017-03-15 14:51:15 -07003892 error_log_destroy(out->error_log);
3893 out->error_log = NULL;
3894
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003895 pthread_cond_destroy(&out->cond);
3896 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003898 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899}
3900
3901static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3902{
3903 struct audio_device *adev = (struct audio_device *)dev;
3904 struct str_parms *parms;
3905 char *str;
3906 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003907 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003908 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003909 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910
Joe Onorato188b6222016-03-01 11:02:27 -08003911 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003912
3913 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914
3915 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003916 status = voice_set_parameters(adev, parms);
3917 if (status != 0) {
3918 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003919 }
3920
3921 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3922 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003923 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3925 adev->bluetooth_nrec = true;
3926 else
3927 adev->bluetooth_nrec = false;
3928 }
3929
3930 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3931 if (ret >= 0) {
3932 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3933 adev->screen_off = false;
3934 else
3935 adev->screen_off = true;
3936 }
3937
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003938 ret = str_parms_get_int(parms, "rotation", &val);
3939 if (ret >= 0) {
3940 bool reverse_speakers = false;
3941 switch(val) {
3942 // FIXME: note that the code below assumes that the speakers are in the correct placement
3943 // relative to the user when the device is rotated 90deg from its default rotation. This
3944 // assumption is device-specific, not platform-specific like this code.
3945 case 270:
3946 reverse_speakers = true;
3947 break;
3948 case 0:
3949 case 90:
3950 case 180:
3951 break;
3952 default:
3953 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003954 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003955 }
Eric Laurent03f09432014-03-25 18:09:11 -07003956 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07003957 // check and set swap
3958 // - check if orientation changed and speaker active
3959 // - set rotation and cache the rotation value
3960 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003961 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003962 }
3963
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003964 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3965 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003966 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003967 }
3968
David Linee3fe402017-03-13 10:00:42 -07003969 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3970 if (ret >= 0) {
3971 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003972 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003973 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3974 if (ret >= 0) {
3975 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003976 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003977 }
Eric Laurent99dab492017-06-17 15:19:08 -07003978 } else if (audio_is_usb_in_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);
Eric Laurent99dab492017-06-17 15:19:08 -07003982 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003983 }
3984 }
3985 }
3986
3987 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3988 if (ret >= 0) {
3989 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003990 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003991 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3992 if (ret >= 0) {
3993 const int card = atoi(value);
3994
Eric Laurent99dab492017-06-17 15:19:08 -07003995 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003996 }
Eric Laurent99dab492017-06-17 15:19:08 -07003997 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003998 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3999 if (ret >= 0) {
4000 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004001 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004002 }
4003 }
4004 }
4005
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004006 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004007done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004009 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004010 ALOGV("%s: exit with code(%d)", __func__, status);
4011 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012}
4013
4014static char* adev_get_parameters(const struct audio_hw_device *dev,
4015 const char *keys)
4016{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004017 struct audio_device *adev = (struct audio_device *)dev;
4018 struct str_parms *reply = str_parms_create();
4019 struct str_parms *query = str_parms_create_str(keys);
4020 char *str;
4021
4022 pthread_mutex_lock(&adev->lock);
4023
4024 voice_get_parameters(adev, query, reply);
4025 str = str_parms_to_str(reply);
4026 str_parms_destroy(query);
4027 str_parms_destroy(reply);
4028
4029 pthread_mutex_unlock(&adev->lock);
4030 ALOGV("%s: exit: returns - %s", __func__, str);
4031 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032}
4033
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004034static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035{
4036 return 0;
4037}
4038
Haynes Mathew George5191a852013-09-11 14:19:36 -07004039static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4040{
4041 int ret;
4042 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004043
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004044 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4045
Haynes Mathew George5191a852013-09-11 14:19:36 -07004046 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004047 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004048 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004049
Haynes Mathew George5191a852013-09-11 14:19:36 -07004050 return ret;
4051}
4052
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004053static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054{
4055 return -ENOSYS;
4056}
4057
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004058static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4059 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060{
4061 return -ENOSYS;
4062}
4063
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004064static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065{
4066 return -ENOSYS;
4067}
4068
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004069static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070{
4071 return -ENOSYS;
4072}
4073
4074static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4075{
4076 struct audio_device *adev = (struct audio_device *)dev;
4077
4078 pthread_mutex_lock(&adev->lock);
4079 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004080 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004081 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004082 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4083 voice_is_in_call(adev)) {
4084 voice_stop_call(adev);
4085 adev->current_call_output = NULL;
4086 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087 }
4088 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004089
4090 audio_extn_extspk_set_mode(adev->extspk, mode);
4091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004092 return 0;
4093}
4094
4095static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4096{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004097 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004098 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099
Eric Laurent2bafff12016-03-17 12:17:23 -07004100 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004101 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004102 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4103 ret = audio_extn_hfp_set_mic_mute(adev, state);
4104 } else {
4105 ret = voice_set_mic_mute(adev, state);
4106 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004107 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004108 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004109
4110 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111}
4112
4113static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4114{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004115 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004116 return 0;
4117}
4118
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004119static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004120 const struct audio_config *config)
4121{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004122 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123
Eric Laurent74b55762017-07-09 17:04:53 -07004124 /* Don't know if USB HIFI in this context so use true to be conservative */
4125 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4126 true /*is_usb_hifi */) != 0)
4127 return 0;
4128
vivek mehtaa68fea62017-06-08 19:04:02 -07004129 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4130 config->sample_rate, config->format,
4131 channel_count,
4132 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133}
4134
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004135static bool adev_input_allow_hifi_record(struct audio_device *adev,
4136 audio_devices_t devices,
4137 audio_input_flags_t flags,
4138 audio_source_t source) {
4139 const bool allowed = true;
4140
4141 if (!audio_is_usb_in_device(devices))
4142 return !allowed;
4143
4144 switch (flags) {
4145 case AUDIO_INPUT_FLAG_NONE:
4146 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4147 break;
4148 default:
4149 return !allowed;
4150 }
4151
4152 switch (source) {
4153 case AUDIO_SOURCE_DEFAULT:
4154 case AUDIO_SOURCE_MIC:
4155 case AUDIO_SOURCE_UNPROCESSED:
4156 break;
4157 default:
4158 return !allowed;
4159 }
4160
4161 switch (adev->mode) {
4162 case 0:
4163 break;
4164 default:
4165 return !allowed;
4166 }
4167
4168 return allowed;
4169}
4170
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004172 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004173 audio_devices_t devices,
4174 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004175 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004176 audio_input_flags_t flags,
4177 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004178 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179{
4180 struct audio_device *adev = (struct audio_device *)dev;
4181 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004182 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004183 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004184 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004185 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004186 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4187 devices,
4188 flags,
4189 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004190 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004192
Eric Laurent74b55762017-07-09 17:04:53 -07004193 if (!(is_usb_dev && may_use_hifi_record)) {
4194 if (config->sample_rate == 0)
4195 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4196 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4197 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4198 if (config->format == AUDIO_FORMAT_DEFAULT)
4199 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004200
Eric Laurent74b55762017-07-09 17:04:53 -07004201 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4202
4203 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4204 return -EINVAL;
4205 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004207 if (audio_extn_tfa_98xx_is_supported() &&
4208 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004209 return -EINVAL;
4210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004211 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4212
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004213 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004214 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 in->stream.common.get_sample_rate = in_get_sample_rate;
4217 in->stream.common.set_sample_rate = in_set_sample_rate;
4218 in->stream.common.get_buffer_size = in_get_buffer_size;
4219 in->stream.common.get_channels = in_get_channels;
4220 in->stream.common.get_format = in_get_format;
4221 in->stream.common.set_format = in_set_format;
4222 in->stream.common.standby = in_standby;
4223 in->stream.common.dump = in_dump;
4224 in->stream.common.set_parameters = in_set_parameters;
4225 in->stream.common.get_parameters = in_get_parameters;
4226 in->stream.common.add_audio_effect = in_add_audio_effect;
4227 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4228 in->stream.set_gain = in_set_gain;
4229 in->stream.read = in_read;
4230 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004231 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232
4233 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004234 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004237 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004238 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004239
Haynes Mathew George569b7482017-05-08 14:44:27 -07004240 if (is_usb_dev && may_use_hifi_record) {
4241 /* HiFi record selects an appropriate format, channel, rate combo
4242 depending on sink capabilities*/
4243 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4244 &config->format,
4245 &in->supported_formats[0],
4246 MAX_SUPPORTED_FORMATS,
4247 &config->channel_mask,
4248 &in->supported_channel_masks[0],
4249 MAX_SUPPORTED_CHANNEL_MASKS,
4250 &config->sample_rate,
4251 &in->supported_sample_rates[0],
4252 MAX_SUPPORTED_SAMPLE_RATES);
4253 if (ret != 0) {
4254 ret = -EINVAL;
4255 goto err_open;
4256 }
Eric Laurent74b55762017-07-09 17:04:53 -07004257 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004258 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004259 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004260 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4261 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4262 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4263 bool ret_error = false;
4264 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4265 from HAL is 8_24
4266 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4267 8_24 return error indicating supported format is 8_24
4268 *> In case of any other source requesting 24 bit or float return error
4269 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004270
vivek mehta57ff9b52016-04-28 14:13:08 -07004271 on error flinger will retry with supported format passed
4272 */
4273 if (source != AUDIO_SOURCE_UNPROCESSED) {
4274 config->format = AUDIO_FORMAT_PCM_16_BIT;
4275 ret_error = true;
4276 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4277 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4278 ret_error = true;
4279 }
4280
4281 if (ret_error) {
4282 ret = -EINVAL;
4283 goto err_open;
4284 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004285 }
4286
vivek mehta57ff9b52016-04-28 14:13:08 -07004287 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004288 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004290 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004291 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4292 if (config->sample_rate == 0)
4293 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4294 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4295 config->sample_rate != 8000) {
4296 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4297 ret = -EINVAL;
4298 goto err_open;
4299 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004300
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004301 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4302 config->format = AUDIO_FORMAT_PCM_16_BIT;
4303 ret = -EINVAL;
4304 goto err_open;
4305 }
4306
4307 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4308 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004309 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004310 } else if (is_usb_dev && may_use_hifi_record) {
4311 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4312 in->config = pcm_config_audio_capture;
4313 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004314 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4315 config->sample_rate,
4316 config->format,
4317 channel_count,
4318 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004319 in->config.period_size = buffer_size / frame_size;
4320 in->config.rate = config->sample_rate;
4321 in->af_period_multiplier = 1;
4322 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004323 } else {
4324 in->usecase = USECASE_AUDIO_RECORD;
4325 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004326 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004327 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004328#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004329 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004330#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004331 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004332 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004333 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004334 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004335 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4336 config->sample_rate,
4337 config->format,
4338 channel_count,
4339 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004340 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004341 in->config.rate = config->sample_rate;
4342 in->af_period_multiplier = 1;
4343 } else {
4344 // period size is left untouched for rt mode playback
4345 in->config = pcm_config_audio_capture_rt;
4346 in->af_period_multiplier = af_period_multiplier;
4347 }
4348 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4349 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004350 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004351 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4352 in->config = pcm_config_mmap_capture;
4353 in->stream.start = in_start;
4354 in->stream.stop = in_stop;
4355 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4356 in->stream.get_mmap_position = in_get_mmap_position;
4357 in->af_period_multiplier = 1;
4358 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004359 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004360 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004361 (config->sample_rate == 8000 ||
4362 config->sample_rate == 16000 ||
4363 config->sample_rate == 32000 ||
4364 config->sample_rate == 48000) &&
4365 channel_count == 1) {
4366 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4367 in->config = pcm_config_audio_capture;
4368 frame_size = audio_stream_in_frame_size(&in->stream);
4369 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4370 config->sample_rate,
4371 config->format,
4372 channel_count, false /*is_low_latency*/);
4373 in->config.period_size = buffer_size / frame_size;
4374 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4375 in->config.rate = config->sample_rate;
4376 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004377 } else {
4378 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004379 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004380 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4381 config->sample_rate,
4382 config->format,
4383 channel_count,
4384 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004385 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004386 in->config.rate = config->sample_rate;
4387 in->af_period_multiplier = 1;
4388 }
4389 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4390 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004391 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004394 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004396 /* This stream could be for sound trigger lab,
4397 get sound trigger pcm if present */
4398 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004399
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004400 lock_input_stream(in);
4401 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4402 pthread_mutex_lock(&adev->lock);
4403 in->card_status = adev->card_status;
4404 pthread_mutex_unlock(&adev->lock);
4405 pthread_mutex_unlock(&in->lock);
4406
vivek mehta4a824772017-06-08 19:05:49 -07004407 stream_app_type_cfg_init(&in->app_type_cfg);
4408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004410 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004411 return 0;
4412
4413err_open:
4414 free(in);
4415 *stream_in = NULL;
4416 return ret;
4417}
4418
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004419static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420 struct audio_stream_in *stream)
4421{
Eric Laurent994a6932013-07-17 11:51:42 -07004422 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004423
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004424 // must deregister from sndmonitor first to prevent races
4425 // between the callback and close_stream
4426 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427 in_standby(&stream->common);
4428 free(stream);
4429
4430 return;
4431}
4432
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004433static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434{
4435 return 0;
4436}
4437
Andy Hung31aca912014-03-20 17:14:59 -07004438/* verifies input and output devices and their capabilities.
4439 *
4440 * This verification is required when enabling extended bit-depth or
4441 * sampling rates, as not all qcom products support it.
4442 *
4443 * Suitable for calling only on initialization such as adev_open().
4444 * It fills the audio_device use_case_table[] array.
4445 *
4446 * Has a side-effect that it needs to configure audio routing / devices
4447 * in order to power up the devices and read the device parameters.
4448 * It does not acquire any hw device lock. Should restore the devices
4449 * back to "normal state" upon completion.
4450 */
4451static int adev_verify_devices(struct audio_device *adev)
4452{
4453 /* enumeration is a bit difficult because one really wants to pull
4454 * the use_case, device id, etc from the hidden pcm_device_table[].
4455 * In this case there are the following use cases and device ids.
4456 *
4457 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4458 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004459 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004460 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4461 * [USECASE_AUDIO_RECORD] = {0, 0},
4462 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4463 * [USECASE_VOICE_CALL] = {2, 2},
4464 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004465 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004466 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4467 */
4468
4469 /* should be the usecases enabled in adev_open_input_stream() */
4470 static const int test_in_usecases[] = {
4471 USECASE_AUDIO_RECORD,
4472 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4473 };
4474 /* should be the usecases enabled in adev_open_output_stream()*/
4475 static const int test_out_usecases[] = {
4476 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4477 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4478 };
4479 static const usecase_type_t usecase_type_by_dir[] = {
4480 PCM_PLAYBACK,
4481 PCM_CAPTURE,
4482 };
4483 static const unsigned flags_by_dir[] = {
4484 PCM_OUT,
4485 PCM_IN,
4486 };
4487
4488 size_t i;
4489 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004490 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004491 char info[512]; /* for possible debug info */
4492
4493 for (dir = 0; dir < 2; ++dir) {
4494 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4495 const unsigned flags_dir = flags_by_dir[dir];
4496 const size_t testsize =
4497 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4498 const int *testcases =
4499 dir ? test_in_usecases : test_out_usecases;
4500 const audio_devices_t audio_device =
4501 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4502
4503 for (i = 0; i < testsize; ++i) {
4504 const audio_usecase_t audio_usecase = testcases[i];
4505 int device_id;
4506 snd_device_t snd_device;
4507 struct pcm_params **pparams;
4508 struct stream_out out;
4509 struct stream_in in;
4510 struct audio_usecase uc_info;
4511 int retval;
4512
4513 pparams = &adev->use_case_table[audio_usecase];
4514 pcm_params_free(*pparams); /* can accept null input */
4515 *pparams = NULL;
4516
4517 /* find the device ID for the use case (signed, for error) */
4518 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4519 if (device_id < 0)
4520 continue;
4521
4522 /* prepare structures for device probing */
4523 memset(&uc_info, 0, sizeof(uc_info));
4524 uc_info.id = audio_usecase;
4525 uc_info.type = usecase_type;
4526 if (dir) {
4527 adev->active_input = &in;
4528 memset(&in, 0, sizeof(in));
4529 in.device = audio_device;
4530 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4531 uc_info.stream.in = &in;
4532 } else {
4533 adev->active_input = NULL;
4534 }
4535 memset(&out, 0, sizeof(out));
4536 out.devices = audio_device; /* only field needed in select_devices */
4537 uc_info.stream.out = &out;
4538 uc_info.devices = audio_device;
4539 uc_info.in_snd_device = SND_DEVICE_NONE;
4540 uc_info.out_snd_device = SND_DEVICE_NONE;
4541 list_add_tail(&adev->usecase_list, &uc_info.list);
4542
4543 /* select device - similar to start_(in/out)put_stream() */
4544 retval = select_devices(adev, audio_usecase);
4545 if (retval >= 0) {
4546 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4547#if LOG_NDEBUG == 0
4548 if (*pparams) {
4549 ALOGV("%s: (%s) card %d device %d", __func__,
4550 dir ? "input" : "output", card_id, device_id);
4551 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004552 } else {
4553 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4554 }
4555#endif
4556 }
4557
4558 /* deselect device - similar to stop_(in/out)put_stream() */
4559 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004560 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004561 /* 2. Disable the rx device */
4562 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004563 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004564 list_remove(&uc_info.list);
4565 }
4566 }
4567 adev->active_input = NULL; /* restore adev state */
4568 return 0;
4569}
4570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004571static int adev_close(hw_device_t *device)
4572{
Andy Hung31aca912014-03-20 17:14:59 -07004573 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004574 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004575
4576 if (!adev)
4577 return 0;
4578
4579 pthread_mutex_lock(&adev_init_lock);
4580
4581 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004582 audio_extn_snd_mon_unregister_listener(adev);
4583 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004584 audio_route_free(adev->audio_route);
4585 free(adev->snd_dev_ref_cnt);
4586 platform_deinit(adev->platform);
4587 audio_extn_extspk_deinit(adev->extspk);
4588 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004589 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004590 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4591 pcm_params_free(adev->use_case_table[i]);
4592 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004593 if (adev->adm_deinit)
4594 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004595 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004596 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004597
4598 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004600 return 0;
4601}
4602
Glenn Kasten4f993392014-05-14 07:30:48 -07004603/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4604 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4605 * just that it _might_ work.
4606 */
4607static int period_size_is_plausible_for_low_latency(int period_size)
4608{
4609 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004610 case 48:
4611 case 96:
4612 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004613 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004614 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004615 case 240:
4616 case 320:
4617 case 480:
4618 return 1;
4619 default:
4620 return 0;
4621 }
4622}
4623
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004624static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4625{
4626 int card;
4627 card_status_t status;
4628
4629 if (!parms)
4630 return;
4631
4632 if (parse_snd_card_status(parms, &card, &status) < 0)
4633 return;
4634
4635 pthread_mutex_lock(&adev->lock);
4636 bool valid_cb = (card == adev->snd_card);
4637 if (valid_cb) {
4638 if (adev->card_status != status) {
4639 adev->card_status = status;
4640 platform_snd_card_update(adev->platform, status);
4641 }
4642 }
4643 pthread_mutex_unlock(&adev->lock);
4644 return;
4645}
4646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647static int adev_open(const hw_module_t *module, const char *name,
4648 hw_device_t **device)
4649{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004650 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004651
Eric Laurent2bafff12016-03-17 12:17:23 -07004652 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004653 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004654 pthread_mutex_lock(&adev_init_lock);
4655 if (audio_device_ref_count != 0) {
4656 *device = &adev->device.common;
4657 audio_device_ref_count++;
4658 ALOGV("%s: returning existing instance of adev", __func__);
4659 ALOGV("%s: exit", __func__);
4660 pthread_mutex_unlock(&adev_init_lock);
4661 return 0;
4662 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004663 adev = calloc(1, sizeof(struct audio_device));
4664
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004665 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4668 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4669 adev->device.common.module = (struct hw_module_t *)module;
4670 adev->device.common.close = adev_close;
4671
4672 adev->device.init_check = adev_init_check;
4673 adev->device.set_voice_volume = adev_set_voice_volume;
4674 adev->device.set_master_volume = adev_set_master_volume;
4675 adev->device.get_master_volume = adev_get_master_volume;
4676 adev->device.set_master_mute = adev_set_master_mute;
4677 adev->device.get_master_mute = adev_get_master_mute;
4678 adev->device.set_mode = adev_set_mode;
4679 adev->device.set_mic_mute = adev_set_mic_mute;
4680 adev->device.get_mic_mute = adev_get_mic_mute;
4681 adev->device.set_parameters = adev_set_parameters;
4682 adev->device.get_parameters = adev_get_parameters;
4683 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4684 adev->device.open_output_stream = adev_open_output_stream;
4685 adev->device.close_output_stream = adev_close_output_stream;
4686 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004687
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004688 adev->device.close_input_stream = adev_close_input_stream;
4689 adev->device.dump = adev_dump;
4690
4691 /* Set the default route before the PCM stream is opened */
4692 pthread_mutex_lock(&adev->lock);
4693 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004694 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004695 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004696 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004697 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004698 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004699 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004700 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004701 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702 pthread_mutex_unlock(&adev->lock);
4703
4704 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004705 adev->platform = platform_init(adev);
4706 if (!adev->platform) {
4707 free(adev->snd_dev_ref_cnt);
4708 free(adev);
4709 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4710 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004711 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004712 return -EINVAL;
4713 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004714 adev->extspk = audio_extn_extspk_init(adev);
4715
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004716 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4717 if (adev->visualizer_lib == NULL) {
4718 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4719 } else {
4720 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4721 adev->visualizer_start_output =
4722 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4723 "visualizer_hal_start_output");
4724 adev->visualizer_stop_output =
4725 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4726 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004727 }
4728
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004729 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4730 if (adev->offload_effects_lib == NULL) {
4731 ALOGW("%s: DLOPEN failed for %s", __func__,
4732 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4733 } else {
4734 ALOGV("%s: DLOPEN successful for %s", __func__,
4735 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4736 adev->offload_effects_start_output =
4737 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4738 "offload_effects_bundle_hal_start_output");
4739 adev->offload_effects_stop_output =
4740 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4741 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004742 }
4743
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004744 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4745 if (adev->adm_lib == NULL) {
4746 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4747 } else {
4748 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4749 adev->adm_init = (adm_init_t)
4750 dlsym(adev->adm_lib, "adm_init");
4751 adev->adm_deinit = (adm_deinit_t)
4752 dlsym(adev->adm_lib, "adm_deinit");
4753 adev->adm_register_input_stream = (adm_register_input_stream_t)
4754 dlsym(adev->adm_lib, "adm_register_input_stream");
4755 adev->adm_register_output_stream = (adm_register_output_stream_t)
4756 dlsym(adev->adm_lib, "adm_register_output_stream");
4757 adev->adm_deregister_stream = (adm_deregister_stream_t)
4758 dlsym(adev->adm_lib, "adm_deregister_stream");
4759 adev->adm_request_focus = (adm_request_focus_t)
4760 dlsym(adev->adm_lib, "adm_request_focus");
4761 adev->adm_abandon_focus = (adm_abandon_focus_t)
4762 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004763 adev->adm_set_config = (adm_set_config_t)
4764 dlsym(adev->adm_lib, "adm_set_config");
4765 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4766 dlsym(adev->adm_lib, "adm_request_focus_v2");
4767 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4768 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4769 adev->adm_on_routing_change = (adm_on_routing_change_t)
4770 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004771 }
4772
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004773 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004774 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004775
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004776 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004777
Andy Hung31aca912014-03-20 17:14:59 -07004778 if (k_enable_extended_precision)
4779 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004780
Glenn Kasten4f993392014-05-14 07:30:48 -07004781 char value[PROPERTY_VALUE_MAX];
4782 int trial;
4783 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4784 trial = atoi(value);
4785 if (period_size_is_plausible_for_low_latency(trial)) {
4786 pcm_config_low_latency.period_size = trial;
4787 pcm_config_low_latency.start_threshold = trial / 4;
4788 pcm_config_low_latency.avail_min = trial / 4;
4789 configured_low_latency_capture_period_size = trial;
4790 }
4791 }
4792 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4793 trial = atoi(value);
4794 if (period_size_is_plausible_for_low_latency(trial)) {
4795 configured_low_latency_capture_period_size = trial;
4796 }
4797 }
4798
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004799 // commented as full set of app type cfg is sent from platform
4800 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004801 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004802
4803 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4804 af_period_multiplier = atoi(value);
4805 if (af_period_multiplier < 0) {
4806 af_period_multiplier = 2;
4807 } else if (af_period_multiplier > 4) {
4808 af_period_multiplier = 4;
4809 }
4810 ALOGV("new period_multiplier = %d", af_period_multiplier);
4811 }
4812
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004813 audio_extn_tfa_98xx_init(adev);
4814
vivek mehta1a9b7c02015-06-25 11:49:38 -07004815 pthread_mutex_unlock(&adev_init_lock);
4816
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004817 if (adev->adm_init)
4818 adev->adm_data = adev->adm_init();
4819
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004820 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004821 audio_extn_snd_mon_init();
4822 pthread_mutex_lock(&adev->lock);
4823 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4824 adev->card_status = CARD_STATUS_ONLINE;
4825 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004826 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004827
Eric Laurent2bafff12016-03-17 12:17:23 -07004828 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004829 return 0;
4830}
4831
4832static struct hw_module_methods_t hal_module_methods = {
4833 .open = adev_open,
4834};
4835
4836struct audio_module HAL_MODULE_INFO_SYM = {
4837 .common = {
4838 .tag = HARDWARE_MODULE_TAG,
4839 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4840 .hal_api_version = HARDWARE_HAL_API_VERSION,
4841 .id = AUDIO_HARDWARE_MODULE_ID,
4842 .name = "QCOM Audio HAL",
4843 .author = "Code Aurora Forum",
4844 .methods = &hal_module_methods,
4845 },
4846};