blob: 677d883d59978023eb61d5d55fa098b49575392b [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 Laurentc8400632013-02-14 19:04:54 -08001351 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001352
Eric Laurent994a6932013-07-17 11:51:42 -07001353 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001354 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001355 uc_info = get_usecase_from_list(adev, in->usecase);
1356 if (uc_info == NULL) {
1357 ALOGE("%s: Could not find the usecase (%d) in the list",
1358 __func__, in->usecase);
1359 return -EINVAL;
1360 }
1361
vivek mehta781065c2017-04-04 12:55:01 -07001362 /* Close in-call recording streams */
1363 voice_check_and_stop_incall_rec_usecase(adev, in);
1364
Eric Laurent150dbfe2013-02-27 14:31:02 -08001365 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001366 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001367
1368 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001369 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001370
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001371 list_remove(&uc_info->list);
1372 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373
Eric Laurent994a6932013-07-17 11:51:42 -07001374 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375 return ret;
1376}
1377
1378int start_input_stream(struct stream_in *in)
1379{
1380 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001381 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001382 struct audio_usecase *uc_info;
1383 struct audio_device *adev = in->dev;
1384
Eric Laurent994a6932013-07-17 11:51:42 -07001385 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001386
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001387 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1388 return -EIO;
1389
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001390 if (in->card_status == CARD_STATUS_OFFLINE ||
1391 adev->card_status == CARD_STATUS_OFFLINE) {
1392 ALOGW("in->card_status or adev->card_status offline, try again");
1393 ret = -EAGAIN;
1394 goto error_config;
1395 }
1396
vivek mehta781065c2017-04-04 12:55:01 -07001397 /* Check if source matches incall recording usecase criteria */
1398 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1399 if (ret)
1400 goto error_config;
1401 else
1402 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1403
Eric Laurentb23d5282013-05-14 15:27:20 -07001404 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001405 if (in->pcm_device_id < 0) {
1406 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1407 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001408 ret = -EINVAL;
1409 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001410 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001411
1412 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001413 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1414 uc_info->id = in->usecase;
1415 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001416 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001417 uc_info->devices = in->device;
1418 uc_info->in_snd_device = SND_DEVICE_NONE;
1419 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001421 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001422
1423 audio_extn_perf_lock_acquire();
1424
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001425 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001426
Eric Laurent0e46adf2016-12-16 12:49:24 -08001427 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001428 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001429 ALOGE("%s: pcm stream not ready", __func__);
1430 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001431 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001432 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001433 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001434 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1435 goto error_open;
1436 }
1437 } else {
1438 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1439 unsigned int pcm_open_retry_count = 0;
1440
1441 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1442 flags |= PCM_MMAP | PCM_NOIRQ;
1443 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1444 } else if (in->realtime) {
1445 flags |= PCM_MMAP | PCM_NOIRQ;
1446 }
1447
1448 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1449 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1450
1451 while (1) {
1452 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1453 flags, &in->config);
1454 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1455 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1456 if (in->pcm != NULL) {
1457 pcm_close(in->pcm);
1458 in->pcm = NULL;
1459 }
1460 if (pcm_open_retry_count-- == 0) {
1461 ret = -EIO;
1462 goto error_open;
1463 }
1464 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1465 continue;
1466 }
1467 break;
1468 }
1469
1470 ALOGV("%s: pcm_prepare", __func__);
1471 ret = pcm_prepare(in->pcm);
1472 if (ret < 0) {
1473 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001474 pcm_close(in->pcm);
1475 in->pcm = NULL;
1476 goto error_open;
1477 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001478 if (in->realtime) {
1479 ret = pcm_start(in->pcm);
1480 if (ret < 0) {
1481 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1482 pcm_close(in->pcm);
1483 in->pcm = NULL;
1484 goto error_open;
1485 }
1486 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001487 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001488 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001489 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001490 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001491
Eric Laurent0e46adf2016-12-16 12:49:24 -08001492 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001493
1494error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001496 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001497
1498error_config:
1499 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001500 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001501 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502}
1503
Eric Laurenta1478072015-09-21 17:21:52 -07001504void lock_input_stream(struct stream_in *in)
1505{
1506 pthread_mutex_lock(&in->pre_lock);
1507 pthread_mutex_lock(&in->lock);
1508 pthread_mutex_unlock(&in->pre_lock);
1509}
1510
1511void lock_output_stream(struct stream_out *out)
1512{
1513 pthread_mutex_lock(&out->pre_lock);
1514 pthread_mutex_lock(&out->lock);
1515 pthread_mutex_unlock(&out->pre_lock);
1516}
1517
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001518/* must be called with out->lock locked */
1519static int send_offload_cmd_l(struct stream_out* out, int command)
1520{
1521 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1522
1523 ALOGVV("%s %d", __func__, command);
1524
1525 cmd->cmd = command;
1526 list_add_tail(&out->offload_cmd_list, &cmd->node);
1527 pthread_cond_signal(&out->offload_cond);
1528 return 0;
1529}
1530
1531/* must be called iwth out->lock locked */
1532static void stop_compressed_output_l(struct stream_out *out)
1533{
1534 out->offload_state = OFFLOAD_STATE_IDLE;
1535 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001536 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001537 if (out->compr != NULL) {
1538 compress_stop(out->compr);
1539 while (out->offload_thread_blocked) {
1540 pthread_cond_wait(&out->cond, &out->lock);
1541 }
1542 }
1543}
1544
1545static void *offload_thread_loop(void *context)
1546{
1547 struct stream_out *out = (struct stream_out *) context;
1548 struct listnode *item;
1549
1550 out->offload_state = OFFLOAD_STATE_IDLE;
1551 out->playback_started = 0;
1552
1553 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1554 set_sched_policy(0, SP_FOREGROUND);
1555 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1556
1557 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001558 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001559 for (;;) {
1560 struct offload_cmd *cmd = NULL;
1561 stream_callback_event_t event;
1562 bool send_callback = false;
1563
1564 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1565 __func__, list_empty(&out->offload_cmd_list),
1566 out->offload_state);
1567 if (list_empty(&out->offload_cmd_list)) {
1568 ALOGV("%s SLEEPING", __func__);
1569 pthread_cond_wait(&out->offload_cond, &out->lock);
1570 ALOGV("%s RUNNING", __func__);
1571 continue;
1572 }
1573
1574 item = list_head(&out->offload_cmd_list);
1575 cmd = node_to_item(item, struct offload_cmd, node);
1576 list_remove(item);
1577
1578 ALOGVV("%s STATE %d CMD %d out->compr %p",
1579 __func__, out->offload_state, cmd->cmd, out->compr);
1580
1581 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1582 free(cmd);
1583 break;
1584 }
1585
1586 if (out->compr == NULL) {
1587 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001588 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001589 pthread_cond_signal(&out->cond);
1590 continue;
1591 }
1592 out->offload_thread_blocked = true;
1593 pthread_mutex_unlock(&out->lock);
1594 send_callback = false;
1595 switch(cmd->cmd) {
1596 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1597 compress_wait(out->compr, -1);
1598 send_callback = true;
1599 event = STREAM_CBK_EVENT_WRITE_READY;
1600 break;
1601 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001602 compress_next_track(out->compr);
1603 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001604 send_callback = true;
1605 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001606 /* Resend the metadata for next iteration */
1607 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001608 break;
1609 case OFFLOAD_CMD_DRAIN:
1610 compress_drain(out->compr);
1611 send_callback = true;
1612 event = STREAM_CBK_EVENT_DRAIN_READY;
1613 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001614 case OFFLOAD_CMD_ERROR:
1615 send_callback = true;
1616 event = STREAM_CBK_EVENT_ERROR;
1617 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001618 default:
1619 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1620 break;
1621 }
Eric Laurenta1478072015-09-21 17:21:52 -07001622 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001623 out->offload_thread_blocked = false;
1624 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001625 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001626 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001627 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001628 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001629 free(cmd);
1630 }
1631
1632 pthread_cond_signal(&out->cond);
1633 while (!list_empty(&out->offload_cmd_list)) {
1634 item = list_head(&out->offload_cmd_list);
1635 list_remove(item);
1636 free(node_to_item(item, struct offload_cmd, node));
1637 }
1638 pthread_mutex_unlock(&out->lock);
1639
1640 return NULL;
1641}
1642
1643static int create_offload_callback_thread(struct stream_out *out)
1644{
1645 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1646 list_init(&out->offload_cmd_list);
1647 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1648 offload_thread_loop, out);
1649 return 0;
1650}
1651
1652static int destroy_offload_callback_thread(struct stream_out *out)
1653{
Eric Laurenta1478072015-09-21 17:21:52 -07001654 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001655 stop_compressed_output_l(out);
1656 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1657
1658 pthread_mutex_unlock(&out->lock);
1659 pthread_join(out->offload_thread, (void **) NULL);
1660 pthread_cond_destroy(&out->offload_cond);
1661
1662 return 0;
1663}
1664
Eric Laurent07eeafd2013-10-06 12:52:49 -07001665static bool allow_hdmi_channel_config(struct audio_device *adev)
1666{
1667 struct listnode *node;
1668 struct audio_usecase *usecase;
1669 bool ret = true;
1670
1671 list_for_each(node, &adev->usecase_list) {
1672 usecase = node_to_item(node, struct audio_usecase, list);
1673 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1674 /*
1675 * If voice call is already existing, do not proceed further to avoid
1676 * disabling/enabling both RX and TX devices, CSD calls, etc.
1677 * Once the voice call done, the HDMI channels can be configured to
1678 * max channels of remaining use cases.
1679 */
1680 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001681 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001682 __func__);
1683 ret = false;
1684 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001685 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1686 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001687 "no change in HDMI channels", __func__);
1688 ret = false;
1689 break;
1690 }
1691 }
1692 }
1693 return ret;
1694}
1695
1696static int check_and_set_hdmi_channels(struct audio_device *adev,
1697 unsigned int channels)
1698{
1699 struct listnode *node;
1700 struct audio_usecase *usecase;
1701
1702 /* Check if change in HDMI channel config is allowed */
1703 if (!allow_hdmi_channel_config(adev))
1704 return 0;
1705
1706 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001707 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001708 return 0;
1709 }
1710
1711 platform_set_hdmi_channels(adev->platform, channels);
1712 adev->cur_hdmi_channels = channels;
1713
1714 /*
1715 * Deroute all the playback streams routed to HDMI so that
1716 * the back end is deactivated. Note that backend will not
1717 * be deactivated if any one stream is connected to it.
1718 */
1719 list_for_each(node, &adev->usecase_list) {
1720 usecase = node_to_item(node, struct audio_usecase, list);
1721 if (usecase->type == PCM_PLAYBACK &&
1722 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001723 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001724 }
1725 }
1726
1727 /*
1728 * Enable all the streams disabled above. Now the HDMI backend
1729 * will be activated with new channel configuration
1730 */
1731 list_for_each(node, &adev->usecase_list) {
1732 usecase = node_to_item(node, struct audio_usecase, list);
1733 if (usecase->type == PCM_PLAYBACK &&
1734 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001735 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001736 }
1737 }
1738
1739 return 0;
1740}
1741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742static int stop_output_stream(struct stream_out *out)
1743{
1744 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 struct audio_usecase *uc_info;
1746 struct audio_device *adev = out->dev;
1747
Eric Laurent994a6932013-07-17 11:51:42 -07001748 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001749 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750 uc_info = get_usecase_from_list(adev, out->usecase);
1751 if (uc_info == NULL) {
1752 ALOGE("%s: Could not find the usecase (%d) in the list",
1753 __func__, out->usecase);
1754 return -EINVAL;
1755 }
1756
Haynes Mathew George41f86652014-06-17 14:22:15 -07001757 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1758 if (adev->visualizer_stop_output != NULL)
1759 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1760 if (adev->offload_effects_stop_output != NULL)
1761 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1762 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001763
Eric Laurent150dbfe2013-02-27 14:31:02 -08001764 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001765 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001766
1767 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001768 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001769
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001770 list_remove(&uc_info->list);
1771 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001772
Eric Laurent0499d4f2014-08-25 22:39:29 -05001773 audio_extn_extspk_update(adev->extspk);
1774
Eric Laurent07eeafd2013-10-06 12:52:49 -07001775 /* Must be called after removing the usecase from list */
1776 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1777 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1778
Eric Laurent994a6932013-07-17 11:51:42 -07001779 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 return ret;
1781}
1782
1783int start_output_stream(struct stream_out *out)
1784{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 struct audio_usecase *uc_info;
1787 struct audio_device *adev = out->dev;
1788
Eric Laurent994a6932013-07-17 11:51:42 -07001789 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001790 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001791
1792 if (out->card_status == CARD_STATUS_OFFLINE ||
1793 adev->card_status == CARD_STATUS_OFFLINE) {
1794 ALOGW("out->card_status or adev->card_status offline, try again");
1795 ret = -EAGAIN;
1796 goto error_config;
1797 }
1798
Eric Laurentb23d5282013-05-14 15:27:20 -07001799 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001800 if (out->pcm_device_id < 0) {
1801 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1802 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001803 ret = -EINVAL;
1804 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805 }
1806
1807 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1808 uc_info->id = out->usecase;
1809 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001810 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001811 uc_info->devices = out->devices;
1812 uc_info->in_snd_device = SND_DEVICE_NONE;
1813 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814
Eric Laurent07eeafd2013-10-06 12:52:49 -07001815 /* This must be called before adding this usecase to the list */
1816 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1817 check_and_set_hdmi_channels(adev, out->config.channels);
1818
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001819 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001820
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001821 audio_extn_perf_lock_acquire();
1822
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001823 select_devices(adev, out->usecase);
1824
Eric Laurent0499d4f2014-08-25 22:39:29 -05001825 audio_extn_extspk_update(adev->extspk);
1826
Andy Hung31aca912014-03-20 17:14:59 -07001827 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001828 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001829 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1830 out->pcm = NULL;
1831 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1832 COMPRESS_IN, &out->compr_config);
1833 if (out->compr && !is_compress_ready(out->compr)) {
1834 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1835 compress_close(out->compr);
1836 out->compr = NULL;
1837 ret = -EIO;
1838 goto error_open;
1839 }
1840 if (out->offload_callback)
1841 compress_nonblock(out->compr, out->non_blocking);
1842
1843 if (adev->visualizer_start_output != NULL)
1844 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1845 if (adev->offload_effects_start_output != NULL)
1846 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1847 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001848 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001849 ALOGE("%s: pcm stream not ready", __func__);
1850 goto error_open;
1851 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001852 ret = pcm_start(out->pcm);
1853 if (ret < 0) {
1854 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1855 goto error_open;
1856 }
1857 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001858 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001859 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001860
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001861 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1862 flags |= PCM_MMAP | PCM_NOIRQ;
1863 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001864 } else if (out->realtime) {
1865 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001866 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001867
1868 while (1) {
1869 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1870 flags, &out->config);
1871 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1872 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1873 if (out->pcm != NULL) {
1874 pcm_close(out->pcm);
1875 out->pcm = NULL;
1876 }
1877 if (pcm_open_retry_count-- == 0) {
1878 ret = -EIO;
1879 goto error_open;
1880 }
1881 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1882 continue;
1883 }
1884 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001885 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001886 ALOGV("%s: pcm_prepare", __func__);
1887 if (pcm_is_ready(out->pcm)) {
1888 ret = pcm_prepare(out->pcm);
1889 if (ret < 0) {
1890 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1891 pcm_close(out->pcm);
1892 out->pcm = NULL;
1893 goto error_open;
1894 }
1895 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001896 if (out->realtime) {
1897 ret = pcm_start(out->pcm);
1898 if (ret < 0) {
1899 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1900 pcm_close(out->pcm);
1901 out->pcm = NULL;
1902 goto error_open;
1903 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001904 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001905 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001906 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001907 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001908 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001909 audio_extn_utils_send_app_type_gain(out->dev,
1910 out->app_type_cfg.app_type,
1911 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001912
1913 // consider a scenario where on pause lower layers are tear down.
1914 // so on resume, swap mixer control need to be sent only when
1915 // backend is active, hence rather than sending from enable device
1916 // sending it from start of streamtream
1917
1918 platform_set_swap_channels(adev, true);
1919
Eric Laurent994a6932013-07-17 11:51:42 -07001920 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001921 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001922error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001923 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001925error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001926 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001927}
1928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929static int check_input_parameters(uint32_t sample_rate,
1930 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001931 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001933 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1934 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001935 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1936 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001937 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1938 return -EINVAL;
1939 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001940
Eric Laurent74b55762017-07-09 17:04:53 -07001941 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1942 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001943 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001944 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001945 return -EINVAL;
1946 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001947
1948 switch (sample_rate) {
1949 case 8000:
1950 case 11025:
1951 case 12000:
1952 case 16000:
1953 case 22050:
1954 case 24000:
1955 case 32000:
1956 case 44100:
1957 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001958 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959 break;
1960 default:
vivek mehtadae44712015-07-27 14:13:18 -07001961 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962 return -EINVAL;
1963 }
1964
1965 return 0;
1966}
1967
vivek mehtaa68fea62017-06-08 19:04:02 -07001968static size_t get_stream_buffer_size(size_t duration_ms,
1969 uint32_t sample_rate,
1970 audio_format_t format,
1971 int channel_count,
1972 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001973{
1974 size_t size = 0;
1975
vivek mehtaa68fea62017-06-08 19:04:02 -07001976 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001977 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001978 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001979
1980 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981
Glenn Kasten4f993392014-05-14 07:30:48 -07001982 /* make sure the size is multiple of 32 bytes
1983 * At 48 kHz mono 16-bit PCM:
1984 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1985 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1986 */
1987 size += 0x1f;
1988 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001989
1990 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991}
1992
1993static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1994{
1995 struct stream_out *out = (struct stream_out *)stream;
1996
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998}
1999
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002000static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001{
2002 return -ENOSYS;
2003}
2004
2005static size_t out_get_buffer_size(const struct audio_stream *stream)
2006{
2007 struct stream_out *out = (struct stream_out *)stream;
2008
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002009 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2010 return out->compr_config.fragment_size;
2011 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002012 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002013 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014}
2015
2016static uint32_t out_get_channels(const struct audio_stream *stream)
2017{
2018 struct stream_out *out = (struct stream_out *)stream;
2019
2020 return out->channel_mask;
2021}
2022
2023static audio_format_t out_get_format(const struct audio_stream *stream)
2024{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002025 struct stream_out *out = (struct stream_out *)stream;
2026
2027 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028}
2029
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002030static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031{
2032 return -ENOSYS;
2033}
2034
2035static int out_standby(struct audio_stream *stream)
2036{
2037 struct stream_out *out = (struct stream_out *)stream;
2038 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002039 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002040
Eric Laurent994a6932013-07-17 11:51:42 -07002041 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002042 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043
Eric Laurenta1478072015-09-21 17:21:52 -07002044 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002046 if (adev->adm_deregister_stream)
2047 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002048 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002049 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002050 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2051 if (out->pcm) {
2052 pcm_close(out->pcm);
2053 out->pcm = NULL;
2054 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002055 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002056 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002057 out->playback_started = false;
2058 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002059 } else {
2060 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002061 out->gapless_mdata.encoder_delay = 0;
2062 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063 if (out->compr != NULL) {
2064 compress_close(out->compr);
2065 out->compr = NULL;
2066 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002067 }
Phil Burkbc991042017-02-24 08:06:44 -08002068 if (do_stop) {
2069 stop_output_stream(out);
2070 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002071 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002072 }
2073 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002074 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002075 return 0;
2076}
2077
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002078static int out_on_error(struct audio_stream *stream)
2079{
2080 struct stream_out *out = (struct stream_out *)stream;
2081 struct audio_device *adev = out->dev;
2082 bool do_standby = false;
2083
2084 lock_output_stream(out);
2085 if (!out->standby) {
2086 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2087 stop_compressed_output_l(out);
2088 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2089 } else
2090 do_standby = true;
2091 }
2092 pthread_mutex_unlock(&out->lock);
2093
2094 if (do_standby)
2095 return out_standby(&out->stream.common);
2096
2097 return 0;
2098}
2099
Andy Hung7401c7c2016-09-21 12:41:21 -07002100static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101{
Andy Hung7401c7c2016-09-21 12:41:21 -07002102 struct stream_out *out = (struct stream_out *)stream;
2103
2104 // We try to get the lock for consistency,
2105 // but it isn't necessary for these variables.
2106 // If we're not in standby, we may be blocked on a write.
2107 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2108 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2109 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2110
2111 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002112 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002113 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002114
2115 // dump error info
2116 (void)error_log_dump(
2117 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002118 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002119 (void)power_log_dump(
2120 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 return 0;
2122}
2123
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002124static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2125{
2126 int ret = 0;
2127 char value[32];
2128 struct compr_gapless_mdata tmp_mdata;
2129
2130 if (!out || !parms) {
2131 return -EINVAL;
2132 }
2133
2134 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2135 if (ret >= 0) {
2136 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2137 } else {
2138 return -EINVAL;
2139 }
2140
2141 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2142 if (ret >= 0) {
2143 tmp_mdata.encoder_padding = atoi(value);
2144 } else {
2145 return -EINVAL;
2146 }
2147
2148 out->gapless_mdata = tmp_mdata;
2149 out->send_new_metadata = 1;
2150 ALOGV("%s new encoder delay %u and padding %u", __func__,
2151 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2152
2153 return 0;
2154}
2155
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002156static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2157{
2158 return out == adev->primary_output || out == adev->voice_tx_output;
2159}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2162{
2163 struct stream_out *out = (struct stream_out *)stream;
2164 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002165 struct audio_usecase *usecase;
2166 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 struct str_parms *parms;
2168 char value[32];
2169 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002170 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002171 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172
Eric Laurent2e140aa2016-06-30 17:14:46 -07002173 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002174 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 parms = str_parms_create_str(kvpairs);
2176 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2177 if (ret >= 0) {
2178 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002179 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002180 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002182 /*
2183 * When HDMI cable is unplugged the music playback is paused and
2184 * the policy manager sends routing=0. But the audioflinger
2185 * continues to write data until standby time (3sec).
2186 * As the HDMI core is turned off, the write gets blocked.
2187 * Avoid this by routing audio to speaker until standby.
2188 */
2189 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2190 val == AUDIO_DEVICE_NONE) {
2191 val = AUDIO_DEVICE_OUT_SPEAKER;
2192 }
2193
2194 /*
2195 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002196 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002197 * the select_devices(). But how do we undo this?
2198 *
2199 * For example, music playback is active on headset (deep-buffer usecase)
2200 * and if we go to ringtones and select a ringtone, low-latency usecase
2201 * will be started on headset+speaker. As we can't enable headset+speaker
2202 * and headset devices at the same time, select_devices() switches the music
2203 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2204 * So when the ringtone playback is completed, how do we undo the same?
2205 *
2206 * We are relying on the out_set_parameters() call on deep-buffer output,
2207 * once the ringtone playback is ended.
2208 * NOTE: We should not check if the current devices are same as new devices.
2209 * Because select_devices() must be called to switch back the music
2210 * playback to headset.
2211 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002212 audio_devices_t new_dev = val;
2213 if (new_dev != AUDIO_DEVICE_NONE) {
2214 bool same_dev = out->devices == new_dev;
2215 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002216
Eric Laurenta7657192014-10-09 21:09:33 -07002217 if (output_drives_call(adev, out)) {
2218 if (!voice_is_in_call(adev)) {
2219 if (adev->mode == AUDIO_MODE_IN_CALL) {
2220 adev->current_call_output = out;
2221 ret = voice_start_call(adev);
2222 }
2223 } else {
2224 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002225 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002226 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002227 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002228
2229 if (!out->standby) {
2230 if (!same_dev) {
2231 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002232 // inform adm before actual routing to prevent glitches.
2233 if (adev->adm_on_routing_change) {
2234 adev->adm_on_routing_change(adev->adm_data,
2235 out->handle);
2236 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002237 }
2238 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002239 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002240
2241 // on device switch force swap, lower functions will make sure
2242 // to check if swap is allowed or not.
2243
2244 if (!same_dev)
2245 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002246 }
2247
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002248 }
2249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002251 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002252
2253 /*handles device and call state changes*/
2254 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002256
2257 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2258 parse_compress_metadata(out, parms);
2259 }
2260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002262 ALOGV("%s: exit: code(%d)", __func__, status);
2263 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264}
2265
Haynes Mathew George569b7482017-05-08 14:44:27 -07002266static bool stream_get_parameter_channels(struct str_parms *query,
2267 struct str_parms *reply,
2268 audio_channel_mask_t *supported_channel_masks) {
2269 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002272 size_t i, j;
2273
2274 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2275 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276 value[0] = '\0';
2277 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002278 while (supported_channel_masks[i] != 0) {
2279 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2280 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 if (!first) {
2282 strcat(value, "|");
2283 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002284 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285 first = false;
2286 break;
2287 }
2288 }
2289 i++;
2290 }
2291 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002292 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002293 return ret >= 0;
2294}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002295
Haynes Mathew George569b7482017-05-08 14:44:27 -07002296static bool stream_get_parameter_formats(struct str_parms *query,
2297 struct str_parms *reply,
2298 audio_format_t *supported_formats) {
2299 int ret = -1;
2300 char value[256];
2301 int i;
2302
2303 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2304 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002305 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002306 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002307 case AUDIO_FORMAT_PCM_16_BIT:
2308 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2309 break;
2310 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2311 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2312 break;
2313 case AUDIO_FORMAT_PCM_32_BIT:
2314 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2315 break;
2316 default:
2317 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002318 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002319 break;
2320 }
2321 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002322 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002323 return ret >= 0;
2324}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002325
Haynes Mathew George569b7482017-05-08 14:44:27 -07002326static bool stream_get_parameter_rates(struct str_parms *query,
2327 struct str_parms *reply,
2328 uint32_t *supported_sample_rates) {
2329
2330 int i;
2331 char value[256];
2332 int ret = -1;
2333 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2334 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002335 value[0] = '\0';
2336 i=0;
2337 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002338 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002339 int avail = sizeof(value) - cursor;
2340 ret = snprintf(value + cursor, avail, "%s%d",
2341 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002342 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002343 if (ret < 0 || ret >= avail) {
2344 // if cursor is at the last element of the array
2345 // overwrite with \0 is duplicate work as
2346 // snprintf already put a \0 in place.
2347 // else
2348 // we had space to write the '|' at value[cursor]
2349 // (which will be overwritten) or no space to fill
2350 // the first element (=> cursor == 0)
2351 value[cursor] = '\0';
2352 break;
2353 }
2354 cursor += ret;
2355 ++i;
2356 }
2357 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2358 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002359 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002360 return ret >= 0;
2361}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002362
Haynes Mathew George569b7482017-05-08 14:44:27 -07002363static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2364{
2365 struct stream_out *out = (struct stream_out *)stream;
2366 struct str_parms *query = str_parms_create_str(keys);
2367 char *str;
2368 struct str_parms *reply = str_parms_create();
2369 bool replied = false;
2370 ALOGV("%s: enter: keys - %s", __func__, keys);
2371
2372 replied |= stream_get_parameter_channels(query, reply,
2373 &out->supported_channel_masks[0]);
2374 replied |= stream_get_parameter_formats(query, reply,
2375 &out->supported_formats[0]);
2376 replied |= stream_get_parameter_rates(query, reply,
2377 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002378 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379 str = str_parms_to_str(reply);
2380 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002381 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 }
2383 str_parms_destroy(query);
2384 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002385 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386 return str;
2387}
2388
2389static uint32_t out_get_latency(const struct audio_stream_out *stream)
2390{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002391 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392 struct stream_out *out = (struct stream_out *)stream;
2393
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002394 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2395 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002396 else if ((out->realtime) ||
2397 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002398 // since the buffer won't be filled up faster than realtime,
2399 // return a smaller number
2400 period_ms = (out->af_period_multiplier * out->config.period_size *
2401 1000) / (out->config.rate);
2402 hw_delay = platform_render_latency(out->usecase)/1000;
2403 return period_ms + hw_delay;
2404 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405
2406 return (out->config.period_count * out->config.period_size * 1000) /
2407 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408}
2409
2410static int out_set_volume(struct audio_stream_out *stream, float left,
2411 float right)
2412{
Eric Laurenta9024de2013-04-04 09:19:12 -07002413 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 int volume[2];
2415
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002416 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002417 /* only take left channel into account: the API is for stereo anyway */
2418 out->muted = (left == 0.0f);
2419 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002420 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2421 const char *mixer_ctl_name = "Compress Playback Volume";
2422 struct audio_device *adev = out->dev;
2423 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002424 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2425 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002426 /* try with the control based on device id */
2427 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2428 PCM_PLAYBACK);
2429 char ctl_name[128] = {0};
2430 snprintf(ctl_name, sizeof(ctl_name),
2431 "Compress Playback %d Volume", pcm_device_id);
2432 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2433 if (!ctl) {
2434 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2435 return -EINVAL;
2436 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 }
2438 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2439 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2440 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2441 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002442 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002443 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2444 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2445 if (!out->standby) {
2446 // if in standby, cached volume will be sent after stream is opened
2447 audio_extn_utils_send_app_type_gain(out->dev,
2448 out->app_type_cfg.app_type,
2449 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002450 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002451 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002452 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454 return -ENOSYS;
2455}
2456
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002457// note: this call is safe only if the stream_cb is
2458// removed first in close_output_stream (as is done now).
2459static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2460{
2461 if (!stream || !parms)
2462 return;
2463
2464 struct stream_out *out = (struct stream_out *)stream;
2465 struct audio_device *adev = out->dev;
2466
2467 card_status_t status;
2468 int card;
2469 if (parse_snd_card_status(parms, &card, &status) < 0)
2470 return;
2471
2472 pthread_mutex_lock(&adev->lock);
2473 bool valid_cb = (card == adev->snd_card);
2474 pthread_mutex_unlock(&adev->lock);
2475
2476 if (!valid_cb)
2477 return;
2478
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002479 lock_output_stream(out);
2480 if (out->card_status != status)
2481 out->card_status = status;
2482 pthread_mutex_unlock(&out->lock);
2483
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002484 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2485 use_case_table[out->usecase],
2486 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2487
2488 if (status == CARD_STATUS_OFFLINE)
2489 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002490
2491 return;
2492}
2493
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002494#ifdef NO_AUDIO_OUT
2495static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002496 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002497{
2498 struct stream_out *out = (struct stream_out *)stream;
2499
2500 /* No Output device supported other than BT for playback.
2501 * Sleep for the amount of buffer duration
2502 */
Eric Laurenta1478072015-09-21 17:21:52 -07002503 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002504 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2505 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002506 out_get_sample_rate(&out->stream.common));
2507 pthread_mutex_unlock(&out->lock);
2508 return bytes;
2509}
2510#endif
2511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2513 size_t bytes)
2514{
2515 struct stream_out *out = (struct stream_out *)stream;
2516 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002517 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002518 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519
Eric Laurenta1478072015-09-21 17:21:52 -07002520 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002521 // this is always nonzero
Andy Hung928efbe2017-06-12 14:05:22 -07002522 const size_t frame_size = audio_stream_out_frame_size(stream);
2523 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002524
Eric Laurent0e46adf2016-12-16 12:49:24 -08002525 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2526 error_code = ERROR_CODE_WRITE;
2527 goto exit;
2528 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002530 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002531 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002533 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002536 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 goto exit;
2538 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002539
2540 if (last_known_cal_step != -1) {
2541 ALOGD("%s: retry previous failed cal level set", __func__);
2542 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002546 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002547 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002548 if (out->send_new_metadata) {
2549 ALOGVV("send new gapless metadata");
2550 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2551 out->send_new_metadata = 0;
2552 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002553 unsigned int avail;
2554 struct timespec tstamp;
2555 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2556 /* Do not limit write size if the available frames count is unknown */
2557 if (ret != 0) {
2558 avail = bytes;
2559 }
2560 if (avail == 0) {
2561 ret = 0;
2562 } else {
2563 if (avail > bytes) {
2564 avail = bytes;
2565 }
2566 ret = compress_write(out->compr, buffer, avail);
2567 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2568 __func__, avail, ret);
2569 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002570
Eric Laurent6e895242013-09-05 16:10:57 -07002571 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002572 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2573 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002574 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002575 compress_start(out->compr);
2576 out->playback_started = 1;
2577 out->offload_state = OFFLOAD_STATE_PLAYING;
2578 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002579 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002580 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002581 } else {
2582 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002583 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002584 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002585 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002586 return ret;
2587 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002588 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 if (out->pcm) {
2590 if (out->muted)
2591 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002592
Eric Laurent0e46adf2016-12-16 12:49:24 -08002593 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002594
Haynes Mathew George03c40102016-01-29 17:57:48 -08002595 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2596 out->config.rate;
2597 request_out_focus(out, ns);
2598
2599 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2600 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002601 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002602 else
2603 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002604
Haynes Mathew George03c40102016-01-29 17:57:48 -08002605 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002606 } else {
2607 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002608 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 }
2610
2611exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002612 // For PCM we always consume the buffer and return #bytes regardless of ret.
2613 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung928efbe2017-06-12 14:05:22 -07002614 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002615 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002616 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002617
2618 // only get time if needed for logging, as it is a system call on 32 bit devices.
2619 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2620 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2621 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002622
Andy Hung7401c7c2016-09-21 12:41:21 -07002623 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002624 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002625 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2626 ALOGE_IF(out->pcm != NULL,
2627 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung928efbe2017-06-12 14:05:22 -07002628 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002629 // usleep not guaranteed for values over 1 second but we don't limit here.
2630 }
2631 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 pthread_mutex_unlock(&out->lock);
2634
2635 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002636 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002637 if (sleeptime_us != 0)
2638 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002639 } else {
2640 // only log if the data is properly written (out->power_log may be null)
Andy Hung928efbe2017-06-12 14:05:22 -07002641 power_log_log(out->power_log, buffer, frames, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 }
2643 return bytes;
2644}
2645
2646static int out_get_render_position(const struct audio_stream_out *stream,
2647 uint32_t *dsp_frames)
2648{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002649 struct stream_out *out = (struct stream_out *)stream;
2650 *dsp_frames = 0;
2651 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002652 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002653 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002654 unsigned long frames = 0;
2655 // TODO: check return value
2656 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2657 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002658 ALOGVV("%s rendered frames %d sample_rate %d",
2659 __func__, *dsp_frames, out->sample_rate);
2660 }
2661 pthread_mutex_unlock(&out->lock);
2662 return 0;
2663 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002664 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002665}
2666
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002667static int out_add_audio_effect(const struct audio_stream *stream __unused,
2668 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002669{
2670 return 0;
2671}
2672
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002673static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2674 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675{
2676 return 0;
2677}
2678
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002679static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2680 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002682 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683}
2684
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002685static int out_get_presentation_position(const struct audio_stream_out *stream,
2686 uint64_t *frames, struct timespec *timestamp)
2687{
2688 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002689 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002690 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002691
Eric Laurenta1478072015-09-21 17:21:52 -07002692 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002693
Eric Laurent949a0892013-09-20 09:20:13 -07002694 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2695 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002696 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002697 compress_get_tstamp(out->compr, &dsp_frames,
2698 &out->sample_rate);
2699 ALOGVV("%s rendered frames %ld sample_rate %d",
2700 __func__, dsp_frames, out->sample_rate);
2701 *frames = dsp_frames;
2702 ret = 0;
2703 /* this is the best we can do */
2704 clock_gettime(CLOCK_MONOTONIC, timestamp);
2705 }
2706 } else {
2707 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002708 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002709 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2710 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002711 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002712 // This adjustment accounts for buffering after app processor.
2713 // It is based on estimated DSP latency per use case, rather than exact.
2714 signed_frames -=
2715 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2716
Eric Laurent949a0892013-09-20 09:20:13 -07002717 // It would be unusual for this value to be negative, but check just in case ...
2718 if (signed_frames >= 0) {
2719 *frames = signed_frames;
2720 ret = 0;
2721 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002722 }
2723 }
2724 }
2725
2726 pthread_mutex_unlock(&out->lock);
2727
2728 return ret;
2729}
2730
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002731static int out_set_callback(struct audio_stream_out *stream,
2732 stream_callback_t callback, void *cookie)
2733{
2734 struct stream_out *out = (struct stream_out *)stream;
2735
2736 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002737 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002738 out->offload_callback = callback;
2739 out->offload_cookie = cookie;
2740 pthread_mutex_unlock(&out->lock);
2741 return 0;
2742}
2743
2744static int out_pause(struct audio_stream_out* stream)
2745{
2746 struct stream_out *out = (struct stream_out *)stream;
2747 int status = -ENOSYS;
2748 ALOGV("%s", __func__);
2749 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002750 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002751 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2752 status = compress_pause(out->compr);
2753 out->offload_state = OFFLOAD_STATE_PAUSED;
2754 }
2755 pthread_mutex_unlock(&out->lock);
2756 }
2757 return status;
2758}
2759
2760static int out_resume(struct audio_stream_out* stream)
2761{
2762 struct stream_out *out = (struct stream_out *)stream;
2763 int status = -ENOSYS;
2764 ALOGV("%s", __func__);
2765 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2766 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002767 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002768 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2769 status = compress_resume(out->compr);
2770 out->offload_state = OFFLOAD_STATE_PLAYING;
2771 }
2772 pthread_mutex_unlock(&out->lock);
2773 }
2774 return status;
2775}
2776
2777static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2778{
2779 struct stream_out *out = (struct stream_out *)stream;
2780 int status = -ENOSYS;
2781 ALOGV("%s", __func__);
2782 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002783 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002784 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2785 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2786 else
2787 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2788 pthread_mutex_unlock(&out->lock);
2789 }
2790 return status;
2791}
2792
2793static int out_flush(struct audio_stream_out* stream)
2794{
2795 struct stream_out *out = (struct stream_out *)stream;
2796 ALOGV("%s", __func__);
2797 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002798 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002799 stop_compressed_output_l(out);
2800 pthread_mutex_unlock(&out->lock);
2801 return 0;
2802 }
2803 return -ENOSYS;
2804}
2805
Eric Laurent0e46adf2016-12-16 12:49:24 -08002806static int out_stop(const struct audio_stream_out* stream)
2807{
2808 struct stream_out *out = (struct stream_out *)stream;
2809 struct audio_device *adev = out->dev;
2810 int ret = -ENOSYS;
2811
2812 ALOGV("%s", __func__);
2813 pthread_mutex_lock(&adev->lock);
2814 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2815 out->playback_started && out->pcm != NULL) {
2816 pcm_stop(out->pcm);
2817 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002818 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002819 }
2820 pthread_mutex_unlock(&adev->lock);
2821 return ret;
2822}
2823
2824static int out_start(const struct audio_stream_out* stream)
2825{
2826 struct stream_out *out = (struct stream_out *)stream;
2827 struct audio_device *adev = out->dev;
2828 int ret = -ENOSYS;
2829
2830 ALOGV("%s", __func__);
2831 pthread_mutex_lock(&adev->lock);
2832 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2833 !out->playback_started && out->pcm != NULL) {
2834 ret = start_output_stream(out);
2835 if (ret == 0) {
2836 out->playback_started = true;
2837 }
2838 }
2839 pthread_mutex_unlock(&adev->lock);
2840 return ret;
2841}
2842
Phil Burkbc991042017-02-24 08:06:44 -08002843/*
2844 * Modify config->period_count based on min_size_frames
2845 */
2846static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2847{
2848 int periodCountRequested = (min_size_frames + config->period_size - 1)
2849 / config->period_size;
2850 int periodCount = MMAP_PERIOD_COUNT_MIN;
2851
2852 ALOGV("%s original config.period_size = %d config.period_count = %d",
2853 __func__, config->period_size, config->period_count);
2854
2855 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2856 periodCount *= 2;
2857 }
2858 config->period_count = periodCount;
2859
2860 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2861}
2862
Eric Laurent0e46adf2016-12-16 12:49:24 -08002863static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2864 int32_t min_size_frames,
2865 struct audio_mmap_buffer_info *info)
2866{
2867 struct stream_out *out = (struct stream_out *)stream;
2868 struct audio_device *adev = out->dev;
2869 int ret = 0;
2870 unsigned int offset1;
2871 unsigned int frames1;
2872 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002873 uint32_t mmap_size;
2874 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002875
2876 ALOGV("%s", __func__);
2877 pthread_mutex_lock(&adev->lock);
2878
2879 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002880 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002881 ret = -EINVAL;
2882 goto exit;
2883 }
2884 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002885 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002886 ret = -ENOSYS;
2887 goto exit;
2888 }
2889 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2890 if (out->pcm_device_id < 0) {
2891 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2892 __func__, out->pcm_device_id, out->usecase);
2893 ret = -EINVAL;
2894 goto exit;
2895 }
Phil Burkbc991042017-02-24 08:06:44 -08002896
2897 adjust_mmap_period_count(&out->config, min_size_frames);
2898
Eric Laurent0e46adf2016-12-16 12:49:24 -08002899 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2900 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2901 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2902 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2903 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2904 step = "open";
2905 ret = -ENODEV;
2906 goto exit;
2907 }
2908 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2909 if (ret < 0) {
2910 step = "begin";
2911 goto exit;
2912 }
2913 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002914 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002915 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002916 ret = platform_get_mmap_data_fd(adev->platform,
2917 out->pcm_device_id, 0 /*playback*/,
2918 &info->shared_memory_fd,
2919 &mmap_size);
2920 if (ret < 0) {
2921 // Fall back to non exclusive mode
2922 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2923 } else {
2924 if (mmap_size < buffer_size) {
2925 step = "mmap";
2926 goto exit;
2927 }
2928 // FIXME: indicate exclusive mode support by returning a negative buffer size
2929 info->buffer_size_frames *= -1;
2930 }
2931 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002932
2933 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2934 if (ret < 0) {
2935 step = "commit";
2936 goto exit;
2937 }
Phil Burkbc991042017-02-24 08:06:44 -08002938
2939 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002940 ret = 0;
2941
2942 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2943 __func__, info->shared_memory_address, info->buffer_size_frames);
2944
2945exit:
2946 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002947 if (out->pcm == NULL) {
2948 ALOGE("%s: %s - %d", __func__, step, ret);
2949 } else {
2950 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002951 pcm_close(out->pcm);
2952 out->pcm = NULL;
2953 }
2954 }
2955 pthread_mutex_unlock(&adev->lock);
2956 return ret;
2957}
2958
2959static int out_get_mmap_position(const struct audio_stream_out *stream,
2960 struct audio_mmap_position *position)
2961{
2962 struct stream_out *out = (struct stream_out *)stream;
2963 ALOGVV("%s", __func__);
2964 if (position == NULL) {
2965 return -EINVAL;
2966 }
2967 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2968 return -ENOSYS;
2969 }
2970 if (out->pcm == NULL) {
2971 return -ENOSYS;
2972 }
2973
2974 struct timespec ts = { 0, 0 };
2975 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2976 if (ret < 0) {
2977 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2978 return ret;
2979 }
Andy Hungfc044e12017-03-20 09:24:22 -07002980 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002981 return 0;
2982}
2983
2984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985/** audio_stream_in implementation **/
2986static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2987{
2988 struct stream_in *in = (struct stream_in *)stream;
2989
2990 return in->config.rate;
2991}
2992
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002993static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994{
2995 return -ENOSYS;
2996}
2997
2998static size_t in_get_buffer_size(const struct audio_stream *stream)
2999{
3000 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003001 return in->config.period_size * in->af_period_multiplier *
3002 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003}
3004
3005static uint32_t in_get_channels(const struct audio_stream *stream)
3006{
3007 struct stream_in *in = (struct stream_in *)stream;
3008
3009 return in->channel_mask;
3010}
3011
vivek mehta4ed66e62016-04-15 23:33:34 -07003012static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013{
vivek mehta4ed66e62016-04-15 23:33:34 -07003014 struct stream_in *in = (struct stream_in *)stream;
3015 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016}
3017
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003018static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019{
3020 return -ENOSYS;
3021}
3022
3023static int in_standby(struct audio_stream *stream)
3024{
3025 struct stream_in *in = (struct stream_in *)stream;
3026 struct audio_device *adev = in->dev;
3027 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003028 bool do_stop = true;
3029
Eric Laurent994a6932013-07-17 11:51:42 -07003030 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003031
3032 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003033
3034 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003035 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003036 audio_extn_sound_trigger_stop_lab(in);
3037 in->standby = true;
3038 }
3039
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003041 if (adev->adm_deregister_stream)
3042 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3043
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003044 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003045 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003046 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003047 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003048 in->capture_started = false;
3049 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003050 if (in->pcm) {
3051 pcm_close(in->pcm);
3052 in->pcm = NULL;
3053 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003054 adev->enable_voicerx = false;
3055 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003056 if (do_stop) {
3057 status = stop_input_stream(in);
3058 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003059 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 }
3061 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003062 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 return status;
3064}
3065
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003066static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067{
3068 return 0;
3069}
3070
3071static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3072{
3073 struct stream_in *in = (struct stream_in *)stream;
3074 struct audio_device *adev = in->dev;
3075 struct str_parms *parms;
3076 char *str;
3077 char value[32];
3078 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003079 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080
Eric Laurent994a6932013-07-17 11:51:42 -07003081 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 parms = str_parms_create_str(kvpairs);
3083
3084 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3085
Eric Laurenta1478072015-09-21 17:21:52 -07003086 lock_input_stream(in);
3087
Eric Laurent150dbfe2013-02-27 14:31:02 -08003088 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 if (ret >= 0) {
3090 val = atoi(value);
3091 /* no audio source uses val == 0 */
3092 if ((in->source != val) && (val != 0)) {
3093 in->source = val;
3094 }
3095 }
3096
3097 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099 if (ret >= 0) {
3100 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003101 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 in->device = val;
3103 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003104 if (!in->standby) {
3105 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003106 // inform adm before actual routing to prevent glitches.
3107 if (adev->adm_on_routing_change) {
3108 adev->adm_on_routing_change(adev->adm_data,
3109 in->capture_handle);
3110 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003111 select_devices(adev, in->usecase);
3112 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003113 }
3114 }
3115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003117 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118
3119 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003120 ALOGV("%s: exit: status(%d)", __func__, status);
3121 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122}
3123
Haynes Mathew George569b7482017-05-08 14:44:27 -07003124static char* in_get_parameters(const struct audio_stream *stream,
3125 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003126{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003127 struct stream_in *in = (struct stream_in *)stream;
3128 struct str_parms *query = str_parms_create_str(keys);
3129 char *str;
3130 struct str_parms *reply = str_parms_create();
3131 bool replied = false;
3132
3133 ALOGV("%s: enter: keys - %s", __func__, keys);
3134 replied |= stream_get_parameter_channels(query, reply,
3135 &in->supported_channel_masks[0]);
3136 replied |= stream_get_parameter_formats(query, reply,
3137 &in->supported_formats[0]);
3138 replied |= stream_get_parameter_rates(query, reply,
3139 &in->supported_sample_rates[0]);
3140 if (replied) {
3141 str = str_parms_to_str(reply);
3142 } else {
3143 str = strdup(keys);
3144 }
3145 str_parms_destroy(query);
3146 str_parms_destroy(reply);
3147 ALOGV("%s: exit: returns - %s", __func__, str);
3148 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149}
3150
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003151static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003153 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154}
3155
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003156static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3157{
3158 if (!stream || !parms)
3159 return;
3160
3161 struct stream_in *in = (struct stream_in *)stream;
3162 struct audio_device *adev = in->dev;
3163
3164 card_status_t status;
3165 int card;
3166 if (parse_snd_card_status(parms, &card, &status) < 0)
3167 return;
3168
3169 pthread_mutex_lock(&adev->lock);
3170 bool valid_cb = (card == adev->snd_card);
3171 pthread_mutex_unlock(&adev->lock);
3172
3173 if (!valid_cb)
3174 return;
3175
3176 lock_input_stream(in);
3177 if (in->card_status != status)
3178 in->card_status = status;
3179 pthread_mutex_unlock(&in->lock);
3180
3181 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3182 use_case_table[in->usecase],
3183 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3184
3185 // a better solution would be to report error back to AF and let
3186 // it put the stream to standby
3187 if (status == CARD_STATUS_OFFLINE)
3188 in_standby(&in->stream.common);
3189
3190 return;
3191}
3192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3194 size_t bytes)
3195{
3196 struct stream_in *in = (struct stream_in *)stream;
3197 struct audio_device *adev = in->dev;
3198 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003199 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003200
Eric Laurenta1478072015-09-21 17:21:52 -07003201 lock_input_stream(in);
Andy Hung928efbe2017-06-12 14:05:22 -07003202 const size_t frame_size = audio_stream_in_frame_size(stream);
3203 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003204
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003205 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003206 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003207 /* Read from sound trigger HAL */
3208 audio_extn_sound_trigger_read(in, buffer, bytes);
3209 pthread_mutex_unlock(&in->lock);
3210 return bytes;
3211 }
3212
Eric Laurent0e46adf2016-12-16 12:49:24 -08003213 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3214 ret = -ENOSYS;
3215 goto exit;
3216 }
3217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003219 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003220 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003221 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223 goto exit;
3224 }
3225 in->standby = 0;
3226 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227
Haynes Mathew George03c40102016-01-29 17:57:48 -08003228 //what's the duration requested by the client?
3229 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3230 in->config.rate;
3231 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003232
Haynes Mathew George03c40102016-01-29 17:57:48 -08003233 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003235 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003236 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003237 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003238 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003239 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003240 if (ret < 0) {
3241 ALOGE("Failed to read w/err %s", strerror(errno));
3242 ret = -errno;
3243 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003244 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3245 if (bytes % 4 == 0) {
3246 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3247 int_buf_stream = buffer;
3248 for (size_t itt=0; itt < bytes/4 ; itt++) {
3249 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003250 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003251 } else {
3252 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3253 ret = -EINVAL;
3254 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003255 }
3256 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003257 }
3258
Haynes Mathew George03c40102016-01-29 17:57:48 -08003259 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003261 /*
3262 * Instead of writing zeroes here, we could trust the hardware
3263 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003264 * 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 -08003265 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003266 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003267 memset(buffer, 0, bytes);
3268
3269exit:
3270 pthread_mutex_unlock(&in->lock);
3271
3272 if (ret != 0) {
3273 in_standby(&in->stream.common);
3274 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung928efbe2017-06-12 14:05:22 -07003275 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003276 memset(buffer, 0, bytes); // clear return data
3277 }
3278 if (bytes > 0) {
Andy Hung928efbe2017-06-12 14:05:22 -07003279 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280 }
3281 return bytes;
3282}
3283
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003284static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285{
3286 return 0;
3287}
3288
Andy Hung6ebe5962016-01-15 17:46:57 -08003289static int in_get_capture_position(const struct audio_stream_in *stream,
3290 int64_t *frames, int64_t *time)
3291{
3292 if (stream == NULL || frames == NULL || time == NULL) {
3293 return -EINVAL;
3294 }
3295 struct stream_in *in = (struct stream_in *)stream;
3296 int ret = -ENOSYS;
3297
3298 lock_input_stream(in);
3299 if (in->pcm) {
3300 struct timespec timestamp;
3301 unsigned int avail;
3302 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3303 *frames = in->frames_read + avail;
3304 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3305 ret = 0;
3306 }
3307 }
3308 pthread_mutex_unlock(&in->lock);
3309 return ret;
3310}
3311
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003312static int add_remove_audio_effect(const struct audio_stream *stream,
3313 effect_handle_t effect,
3314 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003316 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003317 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003318 int status = 0;
3319 effect_descriptor_t desc;
3320
3321 status = (*effect)->get_descriptor(effect, &desc);
3322 if (status != 0)
3323 return status;
3324
Eric Laurenta1478072015-09-21 17:21:52 -07003325 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003326 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003327 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003328 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003329 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003330 in->enable_aec != enable &&
3331 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3332 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003333 if (!enable)
3334 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003335 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3336 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3337 adev->enable_voicerx = enable;
3338 struct audio_usecase *usecase;
3339 struct listnode *node;
3340 list_for_each(node, &adev->usecase_list) {
3341 usecase = node_to_item(node, struct audio_usecase, list);
3342 if (usecase->type == PCM_PLAYBACK) {
3343 select_devices(adev, usecase->id);
3344 break;
3345 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003346 }
3347 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003348 if (!in->standby)
3349 select_devices(in->dev, in->usecase);
3350 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003351 if (in->enable_ns != enable &&
3352 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3353 in->enable_ns = enable;
3354 if (!in->standby)
3355 select_devices(in->dev, in->usecase);
3356 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003357 pthread_mutex_unlock(&in->dev->lock);
3358 pthread_mutex_unlock(&in->lock);
3359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360 return 0;
3361}
3362
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003363static int in_add_audio_effect(const struct audio_stream *stream,
3364 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365{
Eric Laurent994a6932013-07-17 11:51:42 -07003366 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003367 return add_remove_audio_effect(stream, effect, true);
3368}
3369
3370static int in_remove_audio_effect(const struct audio_stream *stream,
3371 effect_handle_t effect)
3372{
Eric Laurent994a6932013-07-17 11:51:42 -07003373 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003374 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375}
3376
Eric Laurent0e46adf2016-12-16 12:49:24 -08003377static int in_stop(const struct audio_stream_in* stream)
3378{
3379 struct stream_in *in = (struct stream_in *)stream;
3380 struct audio_device *adev = in->dev;
3381
3382 int ret = -ENOSYS;
3383 ALOGV("%s", __func__);
3384 pthread_mutex_lock(&adev->lock);
3385 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3386 in->capture_started && in->pcm != NULL) {
3387 pcm_stop(in->pcm);
3388 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003389 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003390 }
3391 pthread_mutex_unlock(&adev->lock);
3392 return ret;
3393}
3394
3395static int in_start(const struct audio_stream_in* stream)
3396{
3397 struct stream_in *in = (struct stream_in *)stream;
3398 struct audio_device *adev = in->dev;
3399 int ret = -ENOSYS;
3400
3401 ALOGV("%s in %p", __func__, in);
3402 pthread_mutex_lock(&adev->lock);
3403 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3404 !in->capture_started && in->pcm != NULL) {
3405 if (!in->capture_started) {
3406 ret = start_input_stream(in);
3407 if (ret == 0) {
3408 in->capture_started = true;
3409 }
3410 }
3411 }
3412 pthread_mutex_unlock(&adev->lock);
3413 return ret;
3414}
3415
3416static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3417 int32_t min_size_frames,
3418 struct audio_mmap_buffer_info *info)
3419{
3420 struct stream_in *in = (struct stream_in *)stream;
3421 struct audio_device *adev = in->dev;
3422 int ret = 0;
3423 unsigned int offset1;
3424 unsigned int frames1;
3425 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003426 uint32_t mmap_size;
3427 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003428
3429 pthread_mutex_lock(&adev->lock);
3430 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003431
Eric Laurent0e46adf2016-12-16 12:49:24 -08003432 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003433 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003434 ret = -EINVAL;
3435 goto exit;
3436 }
3437 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003438 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003439 ALOGV("%s in %p", __func__, in);
3440 ret = -ENOSYS;
3441 goto exit;
3442 }
3443 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3444 if (in->pcm_device_id < 0) {
3445 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3446 __func__, in->pcm_device_id, in->usecase);
3447 ret = -EINVAL;
3448 goto exit;
3449 }
Phil Burkbc991042017-02-24 08:06:44 -08003450
3451 adjust_mmap_period_count(&in->config, min_size_frames);
3452
Eric Laurent0e46adf2016-12-16 12:49:24 -08003453 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3454 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3455 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3456 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3457 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3458 step = "open";
3459 ret = -ENODEV;
3460 goto exit;
3461 }
3462
3463 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3464 if (ret < 0) {
3465 step = "begin";
3466 goto exit;
3467 }
3468 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003469 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003470 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003471 ret = platform_get_mmap_data_fd(adev->platform,
3472 in->pcm_device_id, 1 /*capture*/,
3473 &info->shared_memory_fd,
3474 &mmap_size);
3475 if (ret < 0) {
3476 // Fall back to non exclusive mode
3477 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3478 } else {
3479 if (mmap_size < buffer_size) {
3480 step = "mmap";
3481 goto exit;
3482 }
3483 // FIXME: indicate exclusive mode support by returning a negative buffer size
3484 info->buffer_size_frames *= -1;
3485 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003486
Haynes Mathew George96483a22017-03-28 14:52:47 -07003487 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003488
3489 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3490 if (ret < 0) {
3491 step = "commit";
3492 goto exit;
3493 }
3494
Phil Burkbc991042017-02-24 08:06:44 -08003495 in->standby = false;
3496 ret = 0;
3497
Eric Laurent0e46adf2016-12-16 12:49:24 -08003498 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3499 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003500
3501exit:
3502 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003503 if (in->pcm == NULL) {
3504 ALOGE("%s: %s - %d", __func__, step, ret);
3505 } else {
3506 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003507 pcm_close(in->pcm);
3508 in->pcm = NULL;
3509 }
3510 }
3511 pthread_mutex_unlock(&adev->lock);
3512 return ret;
3513}
3514
3515static int in_get_mmap_position(const struct audio_stream_in *stream,
3516 struct audio_mmap_position *position)
3517{
3518 struct stream_in *in = (struct stream_in *)stream;
3519 ALOGVV("%s", __func__);
3520 if (position == NULL) {
3521 return -EINVAL;
3522 }
3523 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3524 return -ENOSYS;
3525 }
3526 if (in->pcm == NULL) {
3527 return -ENOSYS;
3528 }
3529 struct timespec ts = { 0, 0 };
3530 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3531 if (ret < 0) {
3532 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3533 return ret;
3534 }
Andy Hungfc044e12017-03-20 09:24:22 -07003535 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003536 return 0;
3537}
3538
3539
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540static int adev_open_output_stream(struct audio_hw_device *dev,
3541 audio_io_handle_t handle,
3542 audio_devices_t devices,
3543 audio_output_flags_t flags,
3544 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003545 struct audio_stream_out **stream_out,
3546 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547{
3548 struct audio_device *adev = (struct audio_device *)dev;
3549 struct stream_out *out;
3550 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003551 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3552 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3553 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3554 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003555
Eric Laurent994a6932013-07-17 11:51:42 -07003556 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 __func__, config->sample_rate, config->channel_mask, devices, flags);
3558 *stream_out = NULL;
3559 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3560
3561 if (devices == AUDIO_DEVICE_NONE)
3562 devices = AUDIO_DEVICE_OUT_SPEAKER;
3563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564 out->flags = flags;
3565 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003566 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003567 out->format = config->format;
3568 out->sample_rate = config->sample_rate;
3569 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3570 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003571 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572
3573 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003574 if (audio_is_linear_pcm(out->format) &&
3575 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003576 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003577 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003578 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003579 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003580 if (config->sample_rate == 0)
3581 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3582 if (config->channel_mask == 0)
3583 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3584 if (config->format == AUDIO_FORMAT_DEFAULT)
3585 config->format = AUDIO_FORMAT_PCM_16_BIT;
3586 } else if (is_usb_dev) {
3587 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3588 &config->format,
3589 &out->supported_formats[0],
3590 MAX_SUPPORTED_FORMATS,
3591 &config->channel_mask,
3592 &out->supported_channel_masks[0],
3593 MAX_SUPPORTED_CHANNEL_MASKS,
3594 &config->sample_rate,
3595 &out->supported_sample_rates[0],
3596 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003597 ALOGV("plugged dev USB ret %d", ret);
3598 } else {
3599 ret = -1;
3600 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003601 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003602 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003603 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003604
Haynes Mathew George569b7482017-05-08 14:44:27 -07003605 out->channel_mask = config->channel_mask;
3606 out->sample_rate = config->sample_rate;
3607 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003608 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3609 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003610 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003612 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003613 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3614 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003615 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003616 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003617 pthread_mutex_lock(&adev->lock);
3618 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3619 pthread_mutex_unlock(&adev->lock);
3620
3621 // reject offload during card offline to allow
3622 // fallback to s/w paths
3623 if (offline) {
3624 ret = -ENODEV;
3625 goto error_open;
3626 }
3627
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003628 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3629 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3630 ALOGE("%s: Unsupported Offload information", __func__);
3631 ret = -EINVAL;
3632 goto error_open;
3633 }
3634 if (!is_supported_format(config->offload_info.format)) {
3635 ALOGE("%s: Unsupported audio format", __func__);
3636 ret = -EINVAL;
3637 goto error_open;
3638 }
3639
3640 out->compr_config.codec = (struct snd_codec *)
3641 calloc(1, sizeof(struct snd_codec));
3642
3643 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3644 if (config->offload_info.channel_mask)
3645 out->channel_mask = config->offload_info.channel_mask;
3646 else if (config->channel_mask)
3647 out->channel_mask = config->channel_mask;
3648 out->format = config->offload_info.format;
3649 out->sample_rate = config->offload_info.sample_rate;
3650
3651 out->stream.set_callback = out_set_callback;
3652 out->stream.pause = out_pause;
3653 out->stream.resume = out_resume;
3654 out->stream.drain = out_drain;
3655 out->stream.flush = out_flush;
3656
3657 out->compr_config.codec->id =
3658 get_snd_codec_id(config->offload_info.format);
3659 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3660 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003661 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003662 out->compr_config.codec->bit_rate =
3663 config->offload_info.bit_rate;
3664 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003665 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003666 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3667
3668 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3669 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003670
3671 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672 create_offload_callback_thread(out);
3673 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3674 __func__, config->offload_info.version,
3675 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003676 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003677 switch (config->sample_rate) {
3678 case 8000:
3679 case 16000:
3680 case 48000:
3681 out->sample_rate = config->sample_rate;
3682 break;
3683 default:
3684 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003685 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003686 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003687 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3688 out->config = pcm_config_afe_proxy_playback;
3689 adev->voice_tx_output = out;
vivek mehtaa68fea62017-06-08 19:04:02 -07003690 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3691 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3692 AUDIO_OUTPUT_FLAG_VOIP_RX))) {
3693 uint32_t buffer_size, frame_size;
3694 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3695 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3696 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3697 out->config = pcm_config_voip;
3698 out->config.format = pcm_format_from_audio_format(config->format);
3699 out->config.rate = config->sample_rate;
3700 out->config.channels =
3701 audio_channel_count_from_out_mask(config->channel_mask);
3702 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3703 config->sample_rate,
3704 config->format,
3705 out->config.channels,
3706 false /*is_low_latency*/);
3707 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3708 out->config.period_size = buffer_size / frame_size;
3709 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3710 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003712 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3713 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3714 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003715 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3716 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3717 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003718 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3719 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003720 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003721 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003722 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3723 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3724 out->config = pcm_config_mmap_playback;
3725 out->stream.start = out_start;
3726 out->stream.stop = out_stop;
3727 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3728 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003729 } else {
3730 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3731 out->config = pcm_config_low_latency;
3732 }
3733 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003734 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003735 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003736 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003737 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003738
3739 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3740 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3741 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3742 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3743 __func__, config->sample_rate, config->format, config->channel_mask);
3744 config->sample_rate = out->sample_rate;
3745 config->format = out->format;
3746 config->channel_mask = out->channel_mask;
3747 ret = -EINVAL;
3748 goto error_open;
3749 }
3750
Andy Hung6fcba9c2014-03-18 11:53:32 -07003751 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3752 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003754 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003755 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003756 adev->primary_output = out;
3757 else {
3758 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003759 ret = -EEXIST;
3760 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003761 }
3762 }
3763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 /* Check if this usecase is already existing */
3765 pthread_mutex_lock(&adev->lock);
3766 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3767 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003769 ret = -EEXIST;
3770 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 }
3772 pthread_mutex_unlock(&adev->lock);
3773
3774 out->stream.common.get_sample_rate = out_get_sample_rate;
3775 out->stream.common.set_sample_rate = out_set_sample_rate;
3776 out->stream.common.get_buffer_size = out_get_buffer_size;
3777 out->stream.common.get_channels = out_get_channels;
3778 out->stream.common.get_format = out_get_format;
3779 out->stream.common.set_format = out_set_format;
3780 out->stream.common.standby = out_standby;
3781 out->stream.common.dump = out_dump;
3782 out->stream.common.set_parameters = out_set_parameters;
3783 out->stream.common.get_parameters = out_get_parameters;
3784 out->stream.common.add_audio_effect = out_add_audio_effect;
3785 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3786 out->stream.get_latency = out_get_latency;
3787 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003788#ifdef NO_AUDIO_OUT
3789 out->stream.write = out_write_for_no_output;
3790#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003791 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003792#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 out->stream.get_render_position = out_get_render_position;
3794 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003795 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796
Eric Laurent0e46adf2016-12-16 12:49:24 -08003797 if (out->realtime)
3798 out->af_period_multiplier = af_period_multiplier;
3799 else
3800 out->af_period_multiplier = 1;
3801
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003803 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003804 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003806 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003807 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003808 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810 config->format = out->stream.common.get_format(&out->stream.common);
3811 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3812 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3813
Andy Hunga452b0a2017-03-15 14:51:15 -07003814 out->error_log = error_log_create(
3815 ERROR_LOG_ENTRIES,
3816 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3817
Andy Hungfc044e12017-03-20 09:24:22 -07003818 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003819 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003820 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003821 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3822 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3823
3824 out->power_log = power_log_create(
3825 config->sample_rate,
3826 audio_channel_count_from_out_mask(config->channel_mask),
3827 config->format,
3828 POWER_LOG_ENTRIES,
3829 POWER_LOG_FRAMES_PER_ENTRY);
3830 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003831
3832 /*
3833 By locking output stream before registering, we allow the callback
3834 to update stream's state only after stream's initial state is set to
3835 adev state.
3836 */
3837 lock_output_stream(out);
3838 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3839 pthread_mutex_lock(&adev->lock);
3840 out->card_status = adev->card_status;
3841 pthread_mutex_unlock(&adev->lock);
3842 pthread_mutex_unlock(&out->lock);
3843
vivek mehta4a824772017-06-08 19:05:49 -07003844 stream_app_type_cfg_init(&out->app_type_cfg);
3845
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003847
Eric Laurent994a6932013-07-17 11:51:42 -07003848 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003850
3851error_open:
3852 free(out);
3853 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003854 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003855 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856}
3857
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003858static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 struct audio_stream_out *stream)
3860{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003861 struct stream_out *out = (struct stream_out *)stream;
3862 struct audio_device *adev = out->dev;
3863
Eric Laurent994a6932013-07-17 11:51:42 -07003864 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003865
3866 // must deregister from sndmonitor first to prevent races
3867 // between the callback and close_stream
3868 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003870 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3871 destroy_offload_callback_thread(out);
3872
3873 if (out->compr_config.codec != NULL)
3874 free(out->compr_config.codec);
3875 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003876
3877 if (adev->voice_tx_output == out)
3878 adev->voice_tx_output = NULL;
3879
Andy Hungfc044e12017-03-20 09:24:22 -07003880 power_log_destroy(out->power_log);
3881 out->power_log = NULL;
3882
Andy Hunga452b0a2017-03-15 14:51:15 -07003883 error_log_destroy(out->error_log);
3884 out->error_log = NULL;
3885
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003886 pthread_cond_destroy(&out->cond);
3887 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003889 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890}
3891
3892static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3893{
3894 struct audio_device *adev = (struct audio_device *)dev;
3895 struct str_parms *parms;
3896 char *str;
3897 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003898 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003900 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901
Joe Onorato188b6222016-03-01 11:02:27 -08003902 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003903
3904 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003905
3906 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003907 status = voice_set_parameters(adev, parms);
3908 if (status != 0) {
3909 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003910 }
3911
3912 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3913 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003914 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003915 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3916 adev->bluetooth_nrec = true;
3917 else
3918 adev->bluetooth_nrec = false;
3919 }
3920
3921 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3922 if (ret >= 0) {
3923 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3924 adev->screen_off = false;
3925 else
3926 adev->screen_off = true;
3927 }
3928
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003929 ret = str_parms_get_int(parms, "rotation", &val);
3930 if (ret >= 0) {
3931 bool reverse_speakers = false;
3932 switch(val) {
3933 // FIXME: note that the code below assumes that the speakers are in the correct placement
3934 // relative to the user when the device is rotated 90deg from its default rotation. This
3935 // assumption is device-specific, not platform-specific like this code.
3936 case 270:
3937 reverse_speakers = true;
3938 break;
3939 case 0:
3940 case 90:
3941 case 180:
3942 break;
3943 default:
3944 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003945 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003946 }
Eric Laurent03f09432014-03-25 18:09:11 -07003947 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07003948 // check and set swap
3949 // - check if orientation changed and speaker active
3950 // - set rotation and cache the rotation value
3951 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003952 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003953 }
3954
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003955 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3956 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003957 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003958 }
3959
David Linee3fe402017-03-13 10:00:42 -07003960 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3961 if (ret >= 0) {
3962 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003963 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003964 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3965 if (ret >= 0) {
3966 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003967 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003968 }
Eric Laurent99dab492017-06-17 15:19:08 -07003969 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003970 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3971 if (ret >= 0) {
3972 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003973 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003974 }
3975 }
3976 }
3977
3978 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3979 if (ret >= 0) {
3980 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003981 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003982 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3983 if (ret >= 0) {
3984 const int card = atoi(value);
3985
Eric Laurent99dab492017-06-17 15:19:08 -07003986 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003987 }
Eric Laurent99dab492017-06-17 15:19:08 -07003988 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003989 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3990 if (ret >= 0) {
3991 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003992 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003993 }
3994 }
3995 }
3996
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003997 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003998done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003999 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004000 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004001 ALOGV("%s: exit with code(%d)", __func__, status);
4002 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004003}
4004
4005static char* adev_get_parameters(const struct audio_hw_device *dev,
4006 const char *keys)
4007{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004008 struct audio_device *adev = (struct audio_device *)dev;
4009 struct str_parms *reply = str_parms_create();
4010 struct str_parms *query = str_parms_create_str(keys);
4011 char *str;
4012
4013 pthread_mutex_lock(&adev->lock);
4014
4015 voice_get_parameters(adev, query, reply);
4016 str = str_parms_to_str(reply);
4017 str_parms_destroy(query);
4018 str_parms_destroy(reply);
4019
4020 pthread_mutex_unlock(&adev->lock);
4021 ALOGV("%s: exit: returns - %s", __func__, str);
4022 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004023}
4024
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004025static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004026{
4027 return 0;
4028}
4029
Haynes Mathew George5191a852013-09-11 14:19:36 -07004030static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4031{
4032 int ret;
4033 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004034
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004035 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4036
Haynes Mathew George5191a852013-09-11 14:19:36 -07004037 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004038 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004039 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004040
Haynes Mathew George5191a852013-09-11 14:19:36 -07004041 return ret;
4042}
4043
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004044static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004045{
4046 return -ENOSYS;
4047}
4048
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004049static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4050 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051{
4052 return -ENOSYS;
4053}
4054
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004055static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004056{
4057 return -ENOSYS;
4058}
4059
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004060static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061{
4062 return -ENOSYS;
4063}
4064
4065static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4066{
4067 struct audio_device *adev = (struct audio_device *)dev;
4068
4069 pthread_mutex_lock(&adev->lock);
4070 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004071 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004073 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4074 voice_is_in_call(adev)) {
4075 voice_stop_call(adev);
4076 adev->current_call_output = NULL;
4077 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078 }
4079 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004080
4081 audio_extn_extspk_set_mode(adev->extspk, mode);
4082
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083 return 0;
4084}
4085
4086static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4087{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004088 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004090
Eric Laurent2bafff12016-03-17 12:17:23 -07004091 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004092 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004093 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4094 ret = audio_extn_hfp_set_mic_mute(adev, state);
4095 } else {
4096 ret = voice_set_mic_mute(adev, state);
4097 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004098 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004099 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004100
4101 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004102}
4103
4104static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4105{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004106 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004107 return 0;
4108}
4109
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004110static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111 const struct audio_config *config)
4112{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004113 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114
Eric Laurent74b55762017-07-09 17:04:53 -07004115 /* Don't know if USB HIFI in this context so use true to be conservative */
4116 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4117 true /*is_usb_hifi */) != 0)
4118 return 0;
4119
vivek mehtaa68fea62017-06-08 19:04:02 -07004120 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4121 config->sample_rate, config->format,
4122 channel_count,
4123 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124}
4125
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004126static bool adev_input_allow_hifi_record(struct audio_device *adev,
4127 audio_devices_t devices,
4128 audio_input_flags_t flags,
4129 audio_source_t source) {
4130 const bool allowed = true;
4131
4132 if (!audio_is_usb_in_device(devices))
4133 return !allowed;
4134
4135 switch (flags) {
4136 case AUDIO_INPUT_FLAG_NONE:
4137 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4138 break;
4139 default:
4140 return !allowed;
4141 }
4142
4143 switch (source) {
4144 case AUDIO_SOURCE_DEFAULT:
4145 case AUDIO_SOURCE_MIC:
4146 case AUDIO_SOURCE_UNPROCESSED:
4147 break;
4148 default:
4149 return !allowed;
4150 }
4151
4152 switch (adev->mode) {
4153 case 0:
4154 break;
4155 default:
4156 return !allowed;
4157 }
4158
4159 return allowed;
4160}
4161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004163 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 audio_devices_t devices,
4165 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004166 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004167 audio_input_flags_t flags,
4168 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004169 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004170{
4171 struct audio_device *adev = (struct audio_device *)dev;
4172 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004173 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004174 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004175 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004176 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004177 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4178 devices,
4179 flags,
4180 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004181 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004183
Eric Laurent74b55762017-07-09 17:04:53 -07004184 if (!(is_usb_dev && may_use_hifi_record)) {
4185 if (config->sample_rate == 0)
4186 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4187 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4188 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4189 if (config->format == AUDIO_FORMAT_DEFAULT)
4190 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004191
Eric Laurent74b55762017-07-09 17:04:53 -07004192 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4193
4194 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4195 return -EINVAL;
4196 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004198 if (audio_extn_tfa_98xx_is_supported() &&
4199 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004200 return -EINVAL;
4201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4203
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004204 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004205 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004206
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207 in->stream.common.get_sample_rate = in_get_sample_rate;
4208 in->stream.common.set_sample_rate = in_set_sample_rate;
4209 in->stream.common.get_buffer_size = in_get_buffer_size;
4210 in->stream.common.get_channels = in_get_channels;
4211 in->stream.common.get_format = in_get_format;
4212 in->stream.common.set_format = in_set_format;
4213 in->stream.common.standby = in_standby;
4214 in->stream.common.dump = in_dump;
4215 in->stream.common.set_parameters = in_set_parameters;
4216 in->stream.common.get_parameters = in_get_parameters;
4217 in->stream.common.add_audio_effect = in_add_audio_effect;
4218 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4219 in->stream.set_gain = in_set_gain;
4220 in->stream.read = in_read;
4221 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004222 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004223
4224 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004225 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004227 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004228 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004229 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004230
Haynes Mathew George569b7482017-05-08 14:44:27 -07004231 if (is_usb_dev && may_use_hifi_record) {
4232 /* HiFi record selects an appropriate format, channel, rate combo
4233 depending on sink capabilities*/
4234 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4235 &config->format,
4236 &in->supported_formats[0],
4237 MAX_SUPPORTED_FORMATS,
4238 &config->channel_mask,
4239 &in->supported_channel_masks[0],
4240 MAX_SUPPORTED_CHANNEL_MASKS,
4241 &config->sample_rate,
4242 &in->supported_sample_rates[0],
4243 MAX_SUPPORTED_SAMPLE_RATES);
4244 if (ret != 0) {
4245 ret = -EINVAL;
4246 goto err_open;
4247 }
Eric Laurent74b55762017-07-09 17:04:53 -07004248 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004249 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004250 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004251 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4252 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4253 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4254 bool ret_error = false;
4255 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4256 from HAL is 8_24
4257 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4258 8_24 return error indicating supported format is 8_24
4259 *> In case of any other source requesting 24 bit or float return error
4260 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004261
vivek mehta57ff9b52016-04-28 14:13:08 -07004262 on error flinger will retry with supported format passed
4263 */
4264 if (source != AUDIO_SOURCE_UNPROCESSED) {
4265 config->format = AUDIO_FORMAT_PCM_16_BIT;
4266 ret_error = true;
4267 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4268 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4269 ret_error = true;
4270 }
4271
4272 if (ret_error) {
4273 ret = -EINVAL;
4274 goto err_open;
4275 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004276 }
4277
vivek mehta57ff9b52016-04-28 14:13:08 -07004278 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004279 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004281 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004282 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4283 if (config->sample_rate == 0)
4284 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4285 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4286 config->sample_rate != 8000) {
4287 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4288 ret = -EINVAL;
4289 goto err_open;
4290 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004291
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004292 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4293 config->format = AUDIO_FORMAT_PCM_16_BIT;
4294 ret = -EINVAL;
4295 goto err_open;
4296 }
4297
4298 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4299 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004300 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004301 } else if (is_usb_dev && may_use_hifi_record) {
4302 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4303 in->config = pcm_config_audio_capture;
4304 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004305 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4306 config->sample_rate,
4307 config->format,
4308 channel_count,
4309 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004310 in->config.period_size = buffer_size / frame_size;
4311 in->config.rate = config->sample_rate;
4312 in->af_period_multiplier = 1;
4313 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004314 } else {
4315 in->usecase = USECASE_AUDIO_RECORD;
4316 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004317 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004318 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004319#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004320 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004321#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004322 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004323 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004324 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004325 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004326 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4327 config->sample_rate,
4328 config->format,
4329 channel_count,
4330 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004331 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004332 in->config.rate = config->sample_rate;
4333 in->af_period_multiplier = 1;
4334 } else {
4335 // period size is left untouched for rt mode playback
4336 in->config = pcm_config_audio_capture_rt;
4337 in->af_period_multiplier = af_period_multiplier;
4338 }
4339 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4340 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004341 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004342 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4343 in->config = pcm_config_mmap_capture;
4344 in->stream.start = in_start;
4345 in->stream.stop = in_stop;
4346 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4347 in->stream.get_mmap_position = in_get_mmap_position;
4348 in->af_period_multiplier = 1;
4349 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004350 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
4351 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004352 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004353 (config->sample_rate == 8000 ||
4354 config->sample_rate == 16000 ||
4355 config->sample_rate == 32000 ||
4356 config->sample_rate == 48000) &&
4357 channel_count == 1) {
4358 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4359 in->config = pcm_config_audio_capture;
4360 frame_size = audio_stream_in_frame_size(&in->stream);
4361 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4362 config->sample_rate,
4363 config->format,
4364 channel_count, false /*is_low_latency*/);
4365 in->config.period_size = buffer_size / frame_size;
4366 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4367 in->config.rate = config->sample_rate;
4368 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004369 } else {
4370 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004371 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004372 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4373 config->sample_rate,
4374 config->format,
4375 channel_count,
4376 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004377 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004378 in->config.rate = config->sample_rate;
4379 in->af_period_multiplier = 1;
4380 }
4381 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4382 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004383 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004386 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004388 /* This stream could be for sound trigger lab,
4389 get sound trigger pcm if present */
4390 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004391
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004392 lock_input_stream(in);
4393 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4394 pthread_mutex_lock(&adev->lock);
4395 in->card_status = adev->card_status;
4396 pthread_mutex_unlock(&adev->lock);
4397 pthread_mutex_unlock(&in->lock);
4398
vivek mehta4a824772017-06-08 19:05:49 -07004399 stream_app_type_cfg_init(&in->app_type_cfg);
4400
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004401 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004402 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403 return 0;
4404
4405err_open:
4406 free(in);
4407 *stream_in = NULL;
4408 return ret;
4409}
4410
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004411static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412 struct audio_stream_in *stream)
4413{
Eric Laurent994a6932013-07-17 11:51:42 -07004414 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004415
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004416 // must deregister from sndmonitor first to prevent races
4417 // between the callback and close_stream
4418 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004419 in_standby(&stream->common);
4420 free(stream);
4421
4422 return;
4423}
4424
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004425static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004426{
4427 return 0;
4428}
4429
Andy Hung31aca912014-03-20 17:14:59 -07004430/* verifies input and output devices and their capabilities.
4431 *
4432 * This verification is required when enabling extended bit-depth or
4433 * sampling rates, as not all qcom products support it.
4434 *
4435 * Suitable for calling only on initialization such as adev_open().
4436 * It fills the audio_device use_case_table[] array.
4437 *
4438 * Has a side-effect that it needs to configure audio routing / devices
4439 * in order to power up the devices and read the device parameters.
4440 * It does not acquire any hw device lock. Should restore the devices
4441 * back to "normal state" upon completion.
4442 */
4443static int adev_verify_devices(struct audio_device *adev)
4444{
4445 /* enumeration is a bit difficult because one really wants to pull
4446 * the use_case, device id, etc from the hidden pcm_device_table[].
4447 * In this case there are the following use cases and device ids.
4448 *
4449 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4450 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004451 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004452 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4453 * [USECASE_AUDIO_RECORD] = {0, 0},
4454 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4455 * [USECASE_VOICE_CALL] = {2, 2},
4456 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004457 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004458 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4459 */
4460
4461 /* should be the usecases enabled in adev_open_input_stream() */
4462 static const int test_in_usecases[] = {
4463 USECASE_AUDIO_RECORD,
4464 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4465 };
4466 /* should be the usecases enabled in adev_open_output_stream()*/
4467 static const int test_out_usecases[] = {
4468 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4469 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4470 };
4471 static const usecase_type_t usecase_type_by_dir[] = {
4472 PCM_PLAYBACK,
4473 PCM_CAPTURE,
4474 };
4475 static const unsigned flags_by_dir[] = {
4476 PCM_OUT,
4477 PCM_IN,
4478 };
4479
4480 size_t i;
4481 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004482 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004483 char info[512]; /* for possible debug info */
4484
4485 for (dir = 0; dir < 2; ++dir) {
4486 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4487 const unsigned flags_dir = flags_by_dir[dir];
4488 const size_t testsize =
4489 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4490 const int *testcases =
4491 dir ? test_in_usecases : test_out_usecases;
4492 const audio_devices_t audio_device =
4493 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4494
4495 for (i = 0; i < testsize; ++i) {
4496 const audio_usecase_t audio_usecase = testcases[i];
4497 int device_id;
4498 snd_device_t snd_device;
4499 struct pcm_params **pparams;
4500 struct stream_out out;
4501 struct stream_in in;
4502 struct audio_usecase uc_info;
4503 int retval;
4504
4505 pparams = &adev->use_case_table[audio_usecase];
4506 pcm_params_free(*pparams); /* can accept null input */
4507 *pparams = NULL;
4508
4509 /* find the device ID for the use case (signed, for error) */
4510 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4511 if (device_id < 0)
4512 continue;
4513
4514 /* prepare structures for device probing */
4515 memset(&uc_info, 0, sizeof(uc_info));
4516 uc_info.id = audio_usecase;
4517 uc_info.type = usecase_type;
4518 if (dir) {
4519 adev->active_input = &in;
4520 memset(&in, 0, sizeof(in));
4521 in.device = audio_device;
4522 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4523 uc_info.stream.in = &in;
4524 } else {
4525 adev->active_input = NULL;
4526 }
4527 memset(&out, 0, sizeof(out));
4528 out.devices = audio_device; /* only field needed in select_devices */
4529 uc_info.stream.out = &out;
4530 uc_info.devices = audio_device;
4531 uc_info.in_snd_device = SND_DEVICE_NONE;
4532 uc_info.out_snd_device = SND_DEVICE_NONE;
4533 list_add_tail(&adev->usecase_list, &uc_info.list);
4534
4535 /* select device - similar to start_(in/out)put_stream() */
4536 retval = select_devices(adev, audio_usecase);
4537 if (retval >= 0) {
4538 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4539#if LOG_NDEBUG == 0
4540 if (*pparams) {
4541 ALOGV("%s: (%s) card %d device %d", __func__,
4542 dir ? "input" : "output", card_id, device_id);
4543 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004544 } else {
4545 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4546 }
4547#endif
4548 }
4549
4550 /* deselect device - similar to stop_(in/out)put_stream() */
4551 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004552 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004553 /* 2. Disable the rx device */
4554 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004555 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004556 list_remove(&uc_info.list);
4557 }
4558 }
4559 adev->active_input = NULL; /* restore adev state */
4560 return 0;
4561}
4562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004563static int adev_close(hw_device_t *device)
4564{
Andy Hung31aca912014-03-20 17:14:59 -07004565 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004566 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004567
4568 if (!adev)
4569 return 0;
4570
4571 pthread_mutex_lock(&adev_init_lock);
4572
4573 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004574 audio_extn_snd_mon_unregister_listener(adev);
4575 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004576 audio_route_free(adev->audio_route);
4577 free(adev->snd_dev_ref_cnt);
4578 platform_deinit(adev->platform);
4579 audio_extn_extspk_deinit(adev->extspk);
4580 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004581 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004582 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4583 pcm_params_free(adev->use_case_table[i]);
4584 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004585 if (adev->adm_deinit)
4586 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004587 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004588 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004589
4590 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004591
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592 return 0;
4593}
4594
Glenn Kasten4f993392014-05-14 07:30:48 -07004595/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4596 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4597 * just that it _might_ work.
4598 */
4599static int period_size_is_plausible_for_low_latency(int period_size)
4600{
4601 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004602 case 48:
4603 case 96:
4604 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004605 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004606 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004607 case 240:
4608 case 320:
4609 case 480:
4610 return 1;
4611 default:
4612 return 0;
4613 }
4614}
4615
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004616static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4617{
4618 int card;
4619 card_status_t status;
4620
4621 if (!parms)
4622 return;
4623
4624 if (parse_snd_card_status(parms, &card, &status) < 0)
4625 return;
4626
4627 pthread_mutex_lock(&adev->lock);
4628 bool valid_cb = (card == adev->snd_card);
4629 if (valid_cb) {
4630 if (adev->card_status != status) {
4631 adev->card_status = status;
4632 platform_snd_card_update(adev->platform, status);
4633 }
4634 }
4635 pthread_mutex_unlock(&adev->lock);
4636 return;
4637}
4638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004639static int adev_open(const hw_module_t *module, const char *name,
4640 hw_device_t **device)
4641{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004642 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004643
Eric Laurent2bafff12016-03-17 12:17:23 -07004644 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004646 pthread_mutex_lock(&adev_init_lock);
4647 if (audio_device_ref_count != 0) {
4648 *device = &adev->device.common;
4649 audio_device_ref_count++;
4650 ALOGV("%s: returning existing instance of adev", __func__);
4651 ALOGV("%s: exit", __func__);
4652 pthread_mutex_unlock(&adev_init_lock);
4653 return 0;
4654 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004655 adev = calloc(1, sizeof(struct audio_device));
4656
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004657 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4660 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4661 adev->device.common.module = (struct hw_module_t *)module;
4662 adev->device.common.close = adev_close;
4663
4664 adev->device.init_check = adev_init_check;
4665 adev->device.set_voice_volume = adev_set_voice_volume;
4666 adev->device.set_master_volume = adev_set_master_volume;
4667 adev->device.get_master_volume = adev_get_master_volume;
4668 adev->device.set_master_mute = adev_set_master_mute;
4669 adev->device.get_master_mute = adev_get_master_mute;
4670 adev->device.set_mode = adev_set_mode;
4671 adev->device.set_mic_mute = adev_set_mic_mute;
4672 adev->device.get_mic_mute = adev_get_mic_mute;
4673 adev->device.set_parameters = adev_set_parameters;
4674 adev->device.get_parameters = adev_get_parameters;
4675 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4676 adev->device.open_output_stream = adev_open_output_stream;
4677 adev->device.close_output_stream = adev_close_output_stream;
4678 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004679
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004680 adev->device.close_input_stream = adev_close_input_stream;
4681 adev->device.dump = adev_dump;
4682
4683 /* Set the default route before the PCM stream is opened */
4684 pthread_mutex_lock(&adev->lock);
4685 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004686 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004687 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004688 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004689 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004690 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004691 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004692 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004693 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004694 pthread_mutex_unlock(&adev->lock);
4695
4696 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004697 adev->platform = platform_init(adev);
4698 if (!adev->platform) {
4699 free(adev->snd_dev_ref_cnt);
4700 free(adev);
4701 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4702 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004703 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004704 return -EINVAL;
4705 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004706 adev->extspk = audio_extn_extspk_init(adev);
4707
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004708 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4709 if (adev->visualizer_lib == NULL) {
4710 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4711 } else {
4712 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4713 adev->visualizer_start_output =
4714 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4715 "visualizer_hal_start_output");
4716 adev->visualizer_stop_output =
4717 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4718 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004719 }
4720
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004721 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4722 if (adev->offload_effects_lib == NULL) {
4723 ALOGW("%s: DLOPEN failed for %s", __func__,
4724 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4725 } else {
4726 ALOGV("%s: DLOPEN successful for %s", __func__,
4727 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4728 adev->offload_effects_start_output =
4729 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4730 "offload_effects_bundle_hal_start_output");
4731 adev->offload_effects_stop_output =
4732 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4733 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004734 }
4735
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004736 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4737 if (adev->adm_lib == NULL) {
4738 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4739 } else {
4740 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4741 adev->adm_init = (adm_init_t)
4742 dlsym(adev->adm_lib, "adm_init");
4743 adev->adm_deinit = (adm_deinit_t)
4744 dlsym(adev->adm_lib, "adm_deinit");
4745 adev->adm_register_input_stream = (adm_register_input_stream_t)
4746 dlsym(adev->adm_lib, "adm_register_input_stream");
4747 adev->adm_register_output_stream = (adm_register_output_stream_t)
4748 dlsym(adev->adm_lib, "adm_register_output_stream");
4749 adev->adm_deregister_stream = (adm_deregister_stream_t)
4750 dlsym(adev->adm_lib, "adm_deregister_stream");
4751 adev->adm_request_focus = (adm_request_focus_t)
4752 dlsym(adev->adm_lib, "adm_request_focus");
4753 adev->adm_abandon_focus = (adm_abandon_focus_t)
4754 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004755 adev->adm_set_config = (adm_set_config_t)
4756 dlsym(adev->adm_lib, "adm_set_config");
4757 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4758 dlsym(adev->adm_lib, "adm_request_focus_v2");
4759 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4760 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4761 adev->adm_on_routing_change = (adm_on_routing_change_t)
4762 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004763 }
4764
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004765 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004766 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004768 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004769
Andy Hung31aca912014-03-20 17:14:59 -07004770 if (k_enable_extended_precision)
4771 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772
Glenn Kasten4f993392014-05-14 07:30:48 -07004773 char value[PROPERTY_VALUE_MAX];
4774 int trial;
4775 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4776 trial = atoi(value);
4777 if (period_size_is_plausible_for_low_latency(trial)) {
4778 pcm_config_low_latency.period_size = trial;
4779 pcm_config_low_latency.start_threshold = trial / 4;
4780 pcm_config_low_latency.avail_min = trial / 4;
4781 configured_low_latency_capture_period_size = trial;
4782 }
4783 }
4784 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4785 trial = atoi(value);
4786 if (period_size_is_plausible_for_low_latency(trial)) {
4787 configured_low_latency_capture_period_size = trial;
4788 }
4789 }
4790
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004791 // commented as full set of app type cfg is sent from platform
4792 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004793 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004794
4795 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4796 af_period_multiplier = atoi(value);
4797 if (af_period_multiplier < 0) {
4798 af_period_multiplier = 2;
4799 } else if (af_period_multiplier > 4) {
4800 af_period_multiplier = 4;
4801 }
4802 ALOGV("new period_multiplier = %d", af_period_multiplier);
4803 }
4804
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004805 audio_extn_tfa_98xx_init(adev);
4806
vivek mehta1a9b7c02015-06-25 11:49:38 -07004807 pthread_mutex_unlock(&adev_init_lock);
4808
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004809 if (adev->adm_init)
4810 adev->adm_data = adev->adm_init();
4811
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004812 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004813 audio_extn_snd_mon_init();
4814 pthread_mutex_lock(&adev->lock);
4815 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4816 adev->card_status = CARD_STATUS_ONLINE;
4817 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004818 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004819
Eric Laurent2bafff12016-03-17 12:17:23 -07004820 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004821 return 0;
4822}
4823
4824static struct hw_module_methods_t hal_module_methods = {
4825 .open = adev_open,
4826};
4827
4828struct audio_module HAL_MODULE_INFO_SYM = {
4829 .common = {
4830 .tag = HARDWARE_MODULE_TAG,
4831 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4832 .hal_api_version = HARDWARE_HAL_API_VERSION,
4833 .id = AUDIO_HARDWARE_MODULE_ID,
4834 .name = "QCOM Audio HAL",
4835 .author = "Code Aurora Forum",
4836 .methods = &hal_module_methods,
4837 },
4838};