blob: 3a4729da1ac5131da85506a69eebccbcd57bc5dd [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>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070054#include "platform_api.h"
55#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070056#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080059#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060
Eric Laurent397db572016-05-11 11:31:47 -070061/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
62 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070063#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070064// 2 buffers causes problems with high bitrate files
65#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066/* ToDo: Check and update a proper value in msec */
67#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070068/* treat as unsigned Q1.13 */
69#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070070#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070071
72/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070073#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070074
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070075#define PROXY_OPEN_RETRY_COUNT 100
76#define PROXY_OPEN_WAIT_TIME 20
77
vivek mehtadae44712015-07-27 14:13:18 -070078#define MIN_CHANNEL_COUNT 1
79#define DEFAULT_CHANNEL_COUNT 2
80
Jean-Michel Trivic0750692015-10-12 12:12:32 -070081#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
82#define MAX_CHANNEL_COUNT 1
83#else
vivek mehtadae44712015-07-27 14:13:18 -070084#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
85#define XSTR(x) STR(x)
86#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#endif
Eric Laurent74b55762017-07-09 17:04:53 -070088#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070089
Haynes Mathew George03c40102016-01-29 17:57:48 -080090#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
91
Glenn Kasten4f993392014-05-14 07:30:48 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurent0e46adf2016-12-16 12:49:24 -080095
96#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080097#define MMAP_PERIOD_COUNT_MIN 32
98#define MMAP_PERIOD_COUNT_MAX 512
99#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800100
Andy Hungd13f0d32017-06-12 13:58:37 -0700101static const int64_t NANOS_PER_SECOND = 1000000000;
Eric Laurent0e46adf2016-12-16 12:49:24 -0800102
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
Haynes Mathew George03c40102016-01-29 17:57:48 -0800323static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
324 int flags __unused)
325{
326 int dir = 0;
327 switch (uc_id) {
328 case USECASE_AUDIO_RECORD_LOW_LATENCY:
329 dir = 1;
330 case USECASE_AUDIO_PLAYBACK_ULL:
331 break;
332 default:
333 return false;
334 }
335
336 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
337 PCM_PLAYBACK : PCM_CAPTURE);
338 if (adev->adm_is_noirq_avail)
339 return adev->adm_is_noirq_avail(adev->adm_data,
340 adev->snd_card, dev_id, dir);
341 return false;
342}
343
344static void register_out_stream(struct stream_out *out)
345{
346 struct audio_device *adev = out->dev;
347 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
348 return;
349
350 if (!adev->adm_register_output_stream)
351 return;
352
353 adev->adm_register_output_stream(adev->adm_data,
354 out->handle,
355 out->flags);
356
357 if (!adev->adm_set_config)
358 return;
359
360 if (out->realtime) {
361 adev->adm_set_config(adev->adm_data,
362 out->handle,
363 out->pcm, &out->config);
364 }
365}
366
367static void register_in_stream(struct stream_in *in)
368{
369 struct audio_device *adev = in->dev;
370 if (!adev->adm_register_input_stream)
371 return;
372
373 adev->adm_register_input_stream(adev->adm_data,
374 in->capture_handle,
375 in->flags);
376
377 if (!adev->adm_set_config)
378 return;
379
380 if (in->realtime) {
381 adev->adm_set_config(adev->adm_data,
382 in->capture_handle,
383 in->pcm,
384 &in->config);
385 }
386}
387
388static void request_out_focus(struct stream_out *out, long ns)
389{
390 struct audio_device *adev = out->dev;
391
Haynes Mathew George03c40102016-01-29 17:57:48 -0800392 if (adev->adm_request_focus_v2) {
393 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
394 } else if (adev->adm_request_focus) {
395 adev->adm_request_focus(adev->adm_data, out->handle);
396 }
397}
398
399static void request_in_focus(struct stream_in *in, long ns)
400{
401 struct audio_device *adev = in->dev;
402
Haynes Mathew George03c40102016-01-29 17:57:48 -0800403 if (adev->adm_request_focus_v2) {
404 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
405 } else if (adev->adm_request_focus) {
406 adev->adm_request_focus(adev->adm_data, in->capture_handle);
407 }
408}
409
410static void release_out_focus(struct stream_out *out, long ns __unused)
411{
412 struct audio_device *adev = out->dev;
413
414 if (adev->adm_abandon_focus)
415 adev->adm_abandon_focus(adev->adm_data, out->handle);
416}
417
418static void release_in_focus(struct stream_in *in, long ns __unused)
419{
420 struct audio_device *adev = in->dev;
421 if (adev->adm_abandon_focus)
422 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
423}
424
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700425static int parse_snd_card_status(struct str_parms * parms, int * card,
426 card_status_t * status)
427{
428 char value[32]={0};
429 char state[32]={0};
430
431 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
432
433 if (ret < 0)
434 return -1;
435
436 // sscanf should be okay as value is of max length 32.
437 // same as sizeof state.
438 if (sscanf(value, "%d,%s", card, state) < 2)
439 return -1;
440
441 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
442 CARD_STATUS_OFFLINE;
443 return 0;
444}
445
vivek mehta1a9b7c02015-06-25 11:49:38 -0700446__attribute__ ((visibility ("default")))
447bool audio_hw_send_gain_dep_calibration(int level) {
448 bool ret_val = false;
449 ALOGV("%s: enter ... ", __func__);
450
451 pthread_mutex_lock(&adev_init_lock);
452
453 if (adev != NULL && adev->platform != NULL) {
454 pthread_mutex_lock(&adev->lock);
455 ret_val = platform_send_gain_dep_cal(adev->platform, level);
456 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700457
458 // if cal set fails, cache level info
459 // if cal set succeds, reset known last cal set
460 if (!ret_val)
461 last_known_cal_step = level;
462 else if (last_known_cal_step != -1)
463 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700464 } else {
465 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
466 }
467
468 pthread_mutex_unlock(&adev_init_lock);
469
470 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
471 return ret_val;
472}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700473
vivek mehtaa8d7c922016-05-25 14:40:44 -0700474__attribute__ ((visibility ("default")))
475int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
476 int table_size) {
477 int ret_val = 0;
478 ALOGV("%s: enter ... ", __func__);
479
480 pthread_mutex_lock(&adev_init_lock);
481 if (adev == NULL) {
482 ALOGW("%s: adev is NULL .... ", __func__);
483 goto done;
484 }
485
486 pthread_mutex_lock(&adev->lock);
487 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
488 pthread_mutex_unlock(&adev->lock);
489done:
490 pthread_mutex_unlock(&adev_init_lock);
491 ALOGV("%s: exit ... ", __func__);
492 return ret_val;
493}
494
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700495static bool is_supported_format(audio_format_t format)
496{
Eric Laurent8251ac82014-07-23 11:00:25 -0700497 switch (format) {
498 case AUDIO_FORMAT_MP3:
499 case AUDIO_FORMAT_AAC_LC:
500 case AUDIO_FORMAT_AAC_HE_V1:
501 case AUDIO_FORMAT_AAC_HE_V2:
502 return true;
503 default:
504 break;
505 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700506 return false;
507}
508
Haynes Mathew George03c40102016-01-29 17:57:48 -0800509static inline bool is_mmap_usecase(audio_usecase_t uc_id)
510{
511 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
512 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
513}
514
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700515static int get_snd_codec_id(audio_format_t format)
516{
517 int id = 0;
518
Eric Laurent8251ac82014-07-23 11:00:25 -0700519 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700520 case AUDIO_FORMAT_MP3:
521 id = SND_AUDIOCODEC_MP3;
522 break;
523 case AUDIO_FORMAT_AAC:
524 id = SND_AUDIOCODEC_AAC;
525 break;
526 default:
527 ALOGE("%s: Unsupported audio format", __func__);
528 }
529
530 return id;
531}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800532
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800533static int audio_ssr_status(struct audio_device *adev)
534{
535 int ret = 0;
536 struct mixer_ctl *ctl;
537 const char *mixer_ctl_name = "Audio SSR Status";
538
539 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
540 ret = mixer_ctl_get_value(ctl, 0);
541 ALOGD("%s: value: %d", __func__, ret);
542 return ret;
543}
544
vivek mehta4a824772017-06-08 19:05:49 -0700545static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
546{
547 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
548}
549
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800550int enable_audio_route(struct audio_device *adev,
551 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700553 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800555
556 if (usecase == NULL)
557 return -EINVAL;
558
559 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
560
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800561 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800563 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700564 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800565
Yamit Mehtae3b99562016-09-16 22:44:00 +0530566 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800567 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800568 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500569 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700570 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700571 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800573 ALOGV("%s: exit", __func__);
574 return 0;
575}
576
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800577int disable_audio_route(struct audio_device *adev,
578 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700580 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800581 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800582
583 if (usecase == NULL)
584 return -EINVAL;
585
586 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700587 if (usecase->type == PCM_CAPTURE)
588 snd_device = usecase->in_snd_device;
589 else
590 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800591 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500592 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700593 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700594 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800595
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800596 ALOGV("%s: exit", __func__);
597 return 0;
598}
599
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800600int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700601 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700603 int i, num_devices = 0;
604 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800605 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800606 if (snd_device < SND_DEVICE_MIN ||
607 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800608 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800609 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800610 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700611
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700612 platform_send_audio_calibration(adev->platform, snd_device);
613
vivek mehtade4849c2016-03-03 17:23:38 -0800614 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700615 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700616 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800617 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700618 }
619
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700620 /* due to the possibility of calibration overwrite between listen
621 and audio, notify sound trigger hal before audio calibration is sent */
622 audio_extn_sound_trigger_update_device_status(snd_device,
623 ST_EVENT_SND_DEVICE_BUSY);
624
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700625 if (audio_extn_spkr_prot_is_enabled())
626 audio_extn_spkr_prot_calib_cancel(adev);
627
zhaoyang yin4211fad2015-06-04 21:13:25 +0800628 audio_extn_dsm_feedback_enable(adev, snd_device, true);
629
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700630 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
631 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
632 audio_extn_spkr_prot_is_enabled()) {
633 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800634 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700635 }
636 if (audio_extn_spkr_prot_start_processing(snd_device)) {
637 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800638 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700639 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700640 } else if (platform_can_split_snd_device(snd_device,
641 &num_devices,
642 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700643 for (i = 0; i < num_devices; i++) {
644 enable_snd_device(adev, new_snd_devices[i]);
645 }
vivek mehtab6506412015-08-07 16:55:17 -0700646 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700647 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800648 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
649 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
650 ALOGE(" %s: Invalid sound device returned", __func__);
651 goto on_error;
652 }
Ed Tam70b5c142016-03-21 19:14:29 -0700653
Eric Laurent2e140aa2016-06-30 17:14:46 -0700654 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800655 audio_route_apply_and_update_path(adev->audio_route, device_name);
656 }
657on_success:
658 adev->snd_dev_ref_cnt[snd_device]++;
659 ret_val = 0;
660on_error:
661 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800662}
663
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800664int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700665 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800666{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700667 int i, num_devices = 0;
668 snd_device_t new_snd_devices[2];
669
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800670 if (snd_device < SND_DEVICE_MIN ||
671 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800672 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800673 return -EINVAL;
674 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700675 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
676 ALOGE("%s: device ref cnt is already 0", __func__);
677 return -EINVAL;
678 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800679 audio_extn_tfa_98xx_disable_speaker(snd_device);
680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 adev->snd_dev_ref_cnt[snd_device]--;
682 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800683 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700685 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700686 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
687 audio_extn_spkr_prot_is_enabled()) {
688 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700689
690 // when speaker device is disabled, reset swap.
691 // will be renabled on usecase start
692 platform_set_swap_channels(adev, false);
693
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700694 } else if (platform_can_split_snd_device(snd_device,
695 &num_devices,
696 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700697 for (i = 0; i < num_devices; i++) {
698 disable_snd_device(adev, new_snd_devices[i]);
699 }
vivek mehtab6506412015-08-07 16:55:17 -0700700 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700701 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800702 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
703 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
704 ALOGE(" %s: Invalid sound device returned", __func__);
705 return -EINVAL;
706 }
707
Eric Laurent2e140aa2016-06-30 17:14:46 -0700708 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800709 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700710 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700711 audio_extn_sound_trigger_update_device_status(snd_device,
712 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713 }
vivek mehtab6506412015-08-07 16:55:17 -0700714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800715 return 0;
716}
717
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700718/*
719 legend:
720 uc - existing usecase
721 new_uc - new usecase
722 d1, d11, d2 - SND_DEVICE enums
723 a1, a2 - corresponding ANDROID device enums
724 B, B1, B2 - backend strings
725
726case 1
727 uc->dev d1 (a1) B1
728 new_uc->dev d1 (a1), d2 (a2) B1, B2
729
730 resolution: disable and enable uc->dev on d1
731
732case 2
733 uc->dev d1 (a1) B1
734 new_uc->dev d11 (a1) B1
735
736 resolution: need to switch uc since d1 and d11 are related
737 (e.g. speaker and voice-speaker)
738 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
739
740case 3
741 uc->dev d1 (a1) B1
742 new_uc->dev d2 (a2) B2
743
744 resolution: no need to switch uc
745
746case 4
747 uc->dev d1 (a1) B
748 new_uc->dev d2 (a2) B
749
750 resolution: disable enable uc-dev on d2 since backends match
751 we cannot enable two streams on two different devices if they
752 share the same backend. e.g. if offload is on speaker device using
753 QUAD_MI2S backend and a low-latency stream is started on voice-handset
754 using the same backend, offload must also be switched to voice-handset.
755
756case 5
757 uc->dev d1 (a1) B
758 new_uc->dev d1 (a1), d2 (a2) B
759
760 resolution: disable enable uc-dev on d2 since backends match
761 we cannot enable two streams on two different devices if they
762 share the same backend.
763
764case 6
765 uc->dev d1 a1 B1
766 new_uc->dev d2 a1 B2
767
768 resolution: no need to switch
769
770case 7
771
772 uc->dev d1 (a1), d2 (a2) B1, B2
773 new_uc->dev d1 B1
774
775 resolution: no need to switch
776
777*/
778static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
779 struct audio_usecase *new_uc,
780 snd_device_t new_snd_device)
781{
782 audio_devices_t a1 = uc->stream.out->devices;
783 audio_devices_t a2 = new_uc->stream.out->devices;
784
785 snd_device_t d1 = uc->out_snd_device;
786 snd_device_t d2 = new_snd_device;
787
788 // Treat as a special case when a1 and a2 are not disjoint
789 if ((a1 != a2) && (a1 & a2)) {
790 snd_device_t d3[2];
791 int num_devices = 0;
792 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
793 &num_devices,
794 d3);
795 if (ret < 0) {
796 if (ret != -ENOSYS) {
797 ALOGW("%s failed to split snd_device %d",
798 __func__,
799 popcount(a1) > 1 ? d1 : d2);
800 }
801 goto end;
802 }
803
804 // NB: case 7 is hypothetical and isn't a practical usecase yet.
805 // But if it does happen, we need to give priority to d2 if
806 // the combo devices active on the existing usecase share a backend.
807 // This is because we cannot have a usecase active on a combo device
808 // and a new usecase requests one device in this combo pair.
809 if (platform_check_backends_match(d3[0], d3[1])) {
810 return d2; // case 5
811 } else {
812 return d1; // case 1
813 }
814 } else {
815 if (platform_check_backends_match(d1, d2)) {
816 return d2; // case 2, 4
817 } else {
818 return d1; // case 6, 3
819 }
820 }
821
822end:
823 return d2; // return whatever was calculated before.
824}
825
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700826static void check_and_route_playback_usecases(struct audio_device *adev,
827 struct audio_usecase *uc_info,
828 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700829{
830 struct listnode *node;
831 struct audio_usecase *usecase;
832 bool switch_device[AUDIO_USECASE_MAX];
833 int i, num_uc_to_switch = 0;
834
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700835 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
836 uc_info,
837 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700838
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700839 /*
840 * This function is to make sure that all the usecases that are active on
841 * the hardware codec backend are always routed to any one device that is
842 * handled by the hardware codec.
843 * For example, if low-latency and deep-buffer usecases are currently active
844 * on speaker and out_set_parameters(headset) is received on low-latency
845 * output, then we have to make sure deep-buffer is also switched to headset,
846 * because of the limitation that both the devices cannot be enabled
847 * at the same time as they share the same backend.
848 */
849 /* Disable all the usecases on the shared backend other than the
850 specified usecase */
851 for (i = 0; i < AUDIO_USECASE_MAX; i++)
852 switch_device[i] = false;
853
854 list_for_each(node, &adev->usecase_list) {
855 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700856 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
857 continue;
858
859 if (force_routing ||
860 (usecase->out_snd_device != snd_device &&
861 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
862 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700863 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
864 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700865 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700866 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700867 switch_device[usecase->id] = true;
868 num_uc_to_switch++;
869 }
870 }
871
872 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 list_for_each(node, &adev->usecase_list) {
874 usecase = node_to_item(node, struct audio_usecase, list);
875 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700876 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900877 }
878 }
879
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700880 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900881 list_for_each(node, &adev->usecase_list) {
882 usecase = node_to_item(node, struct audio_usecase, list);
883 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700884 d_device = derive_playback_snd_device(usecase, uc_info,
885 snd_device);
886 enable_snd_device(adev, d_device);
887 /* Update the out_snd_device before enabling the audio route */
888 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700889 }
890 }
891
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 /* Re-route all the usecases on the shared backend other than the
893 specified usecase to new snd devices */
894 list_for_each(node, &adev->usecase_list) {
895 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700896 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700897 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 }
899 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 }
901}
902
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700903static void check_and_route_capture_usecases(struct audio_device *adev,
904 struct audio_usecase *uc_info,
905 snd_device_t snd_device)
906{
907 struct listnode *node;
908 struct audio_usecase *usecase;
909 bool switch_device[AUDIO_USECASE_MAX];
910 int i, num_uc_to_switch = 0;
911
vivek mehta4ed66e62016-04-15 23:33:34 -0700912 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
913
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700914 /*
915 * This function is to make sure that all the active capture usecases
916 * are always routed to the same input sound device.
917 * For example, if audio-record and voice-call usecases are currently
918 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
919 * is received for voice call then we have to make sure that audio-record
920 * usecase is also switched to earpiece i.e. voice-dmic-ef,
921 * because of the limitation that two devices cannot be enabled
922 * at the same time if they share the same backend.
923 */
924 for (i = 0; i < AUDIO_USECASE_MAX; i++)
925 switch_device[i] = false;
926
927 list_for_each(node, &adev->usecase_list) {
928 usecase = node_to_item(node, struct audio_usecase, list);
929 if (usecase->type != PCM_PLAYBACK &&
930 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700931 usecase->in_snd_device != snd_device &&
932 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700933 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
934 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700935 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700936 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700937 switch_device[usecase->id] = true;
938 num_uc_to_switch++;
939 }
940 }
941
942 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700943 list_for_each(node, &adev->usecase_list) {
944 usecase = node_to_item(node, struct audio_usecase, list);
945 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700946 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700947 }
948 }
949
950 list_for_each(node, &adev->usecase_list) {
951 usecase = node_to_item(node, struct audio_usecase, list);
952 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700953 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700954 }
955 }
956
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700957 /* Re-route all the usecases on the shared backend other than the
958 specified usecase to new snd devices */
959 list_for_each(node, &adev->usecase_list) {
960 usecase = node_to_item(node, struct audio_usecase, list);
961 /* Update the in_snd_device only before enabling the audio route */
962 if (switch_device[usecase->id] ) {
963 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700964 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700965 }
966 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700967 }
968}
969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800970/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700971static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800972{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700973 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700974 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800975
976 switch (channels) {
977 /*
978 * Do not handle stereo output in Multi-channel cases
979 * Stereo case is handled in normal playback path
980 */
981 case 6:
982 ALOGV("%s: HDMI supports 5.1", __func__);
983 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
984 break;
985 case 8:
986 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
987 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
988 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
989 break;
990 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700991 ALOGE("HDMI does not support multi channel playback");
992 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800993 break;
994 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700995 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996}
997
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700998static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
999 uint32_t *supported_sample_rates __unused,
1000 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001001{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001002 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1003 supported_sample_rates,
1004 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001005#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001006 for (ssize_t i=0; i<count; i++) {
1007 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1008 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001009 }
1010#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001011 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001012}
1013
Haynes Mathew George569b7482017-05-08 14:44:27 -07001014static int read_usb_sup_channel_masks(bool is_playback,
1015 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001016 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001017{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001018 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001019 int channel_count;
1020 uint32_t num_masks = 0;
1021 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1022 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001023 }
Eric Laurent74b55762017-07-09 17:04:53 -07001024 if (is_playback) {
1025 // For playback we never report mono because the framework always outputs stereo
1026 channel_count = DEFAULT_CHANNEL_COUNT;
1027 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1028 // above 2 but we want indexed masks here. So we
1029 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1030 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1031 }
1032 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1033 supported_channel_masks[num_masks++] =
1034 audio_channel_mask_for_index_assignment_from_count(channel_count);
1035 }
1036 } else {
1037 // For capture we report all supported channel masks from 1 channel up.
1038 channel_count = MIN_CHANNEL_COUNT;
1039 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1040 // indexed mask
1041 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1042 supported_channel_masks[num_masks++] =
1043 audio_channel_in_mask_from_count(channel_count);
1044 }
1045 }
1046 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1047 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1048 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001049}
1050
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001051static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001052 audio_format_t *supported_formats,
1053 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001054{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001055 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001056 switch (bitwidth) {
1057 case 24:
1058 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001059 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001060 break;
1061 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001062 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001063 break;
1064 case 16:
1065 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001066 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001067 break;
1068 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001069 ALOGV("%s: %s supported format %d", __func__,
1070 is_playback ? "P" : "C", bitwidth);
1071 return 1;
1072}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001073
Haynes Mathew George569b7482017-05-08 14:44:27 -07001074static int read_usb_sup_params_and_compare(bool is_playback,
1075 audio_format_t *format,
1076 audio_format_t *supported_formats,
1077 uint32_t max_formats,
1078 audio_channel_mask_t *mask,
1079 audio_channel_mask_t *supported_channel_masks,
1080 uint32_t max_masks,
1081 uint32_t *rate,
1082 uint32_t *supported_sample_rates,
1083 uint32_t max_rates) {
1084 int ret = 0;
1085 int num_formats;
1086 int num_masks;
1087 int num_rates;
1088 int i;
1089
1090 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1091 max_formats);
1092 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1093 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001094
Haynes Mathew George569b7482017-05-08 14:44:27 -07001095 num_rates = read_usb_sup_sample_rates(is_playback,
1096 supported_sample_rates, max_rates);
1097
1098#define LUT(table, len, what, dflt) \
1099 for (i=0; i<len && (table[i] != what); i++); \
1100 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1101
1102 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1103 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1104 LUT(supported_sample_rates, num_rates, *rate, 0);
1105
1106#undef LUT
1107 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001108}
1109
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001110static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1111{
1112 struct audio_usecase *usecase;
1113 struct listnode *node;
1114
1115 list_for_each(node, &adev->usecase_list) {
1116 usecase = node_to_item(node, struct audio_usecase, list);
1117 if (usecase->type == VOICE_CALL) {
1118 ALOGV("%s: usecase id %d", __func__, usecase->id);
1119 return usecase->id;
1120 }
1121 }
1122 return USECASE_INVALID;
1123}
1124
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001125struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1126 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001127{
1128 struct audio_usecase *usecase;
1129 struct listnode *node;
1130
1131 list_for_each(node, &adev->usecase_list) {
1132 usecase = node_to_item(node, struct audio_usecase, list);
1133 if (usecase->id == uc_id)
1134 return usecase;
1135 }
1136 return NULL;
1137}
1138
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001139int select_devices(struct audio_device *adev,
1140 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001141{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001142 snd_device_t out_snd_device = SND_DEVICE_NONE;
1143 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001144 struct audio_usecase *usecase = NULL;
1145 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001146 struct audio_usecase *hfp_usecase = NULL;
1147 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001148 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001149 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001151 usecase = get_usecase_from_list(adev, uc_id);
1152 if (usecase == NULL) {
1153 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1154 return -EINVAL;
1155 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001157 if ((usecase->type == VOICE_CALL) ||
1158 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001159 out_snd_device = platform_get_output_snd_device(adev->platform,
1160 usecase->stream.out->devices);
1161 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001162 usecase->devices = usecase->stream.out->devices;
1163 } else {
1164 /*
1165 * If the voice call is active, use the sound devices of voice call usecase
1166 * so that it would not result any device switch. All the usecases will
1167 * be switched to new device when select_devices() is called for voice call
1168 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001169 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001171 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001172 vc_usecase = get_usecase_from_list(adev,
1173 get_voice_usecase_id_from_list(adev));
1174 if ((vc_usecase != NULL) &&
1175 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1176 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001177 in_snd_device = vc_usecase->in_snd_device;
1178 out_snd_device = vc_usecase->out_snd_device;
1179 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001180 } else if (audio_extn_hfp_is_active(adev)) {
1181 hfp_ucid = audio_extn_hfp_get_usecase();
1182 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1183 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1184 in_snd_device = hfp_usecase->in_snd_device;
1185 out_snd_device = hfp_usecase->out_snd_device;
1186 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001187 }
1188 if (usecase->type == PCM_PLAYBACK) {
1189 usecase->devices = usecase->stream.out->devices;
1190 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001191 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001192 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001193 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001194 if (usecase->stream.out == adev->primary_output &&
1195 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001196 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1197 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001198 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001199 select_devices(adev, adev->active_input->usecase);
1200 }
1201 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 } else if (usecase->type == PCM_CAPTURE) {
1203 usecase->devices = usecase->stream.in->device;
1204 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001205 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001206 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001207 if (adev->active_input &&
1208 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1209 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001210 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001211 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1212 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1213 } else if (adev->primary_output) {
1214 out_device = adev->primary_output->devices;
1215 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001216 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001217 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001218 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001219 }
1220 }
1221
1222 if (out_snd_device == usecase->out_snd_device &&
1223 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224 return 0;
1225 }
1226
Eric Laurent2bafff12016-03-17 12:17:23 -07001227 if (out_snd_device != SND_DEVICE_NONE &&
1228 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1229 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1230 __func__,
1231 use_case_table[uc_id],
1232 adev->last_logged_snd_device[uc_id][0],
1233 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1234 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1235 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1236 -1,
1237 out_snd_device,
1238 platform_get_snd_device_name(out_snd_device),
1239 platform_get_snd_device_acdb_id(out_snd_device));
1240 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1241 }
1242 if (in_snd_device != SND_DEVICE_NONE &&
1243 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1244 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1245 __func__,
1246 use_case_table[uc_id],
1247 adev->last_logged_snd_device[uc_id][1],
1248 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1249 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1250 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1251 -1,
1252 in_snd_device,
1253 platform_get_snd_device_name(in_snd_device),
1254 platform_get_snd_device_acdb_id(in_snd_device));
1255 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1256 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001258 /*
1259 * Limitation: While in call, to do a device switch we need to disable
1260 * and enable both RX and TX devices though one of them is same as current
1261 * device.
1262 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001263 if ((usecase->type == VOICE_CALL) &&
1264 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1265 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001266 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001267 /* Disable sidetone only if voice call already exists */
1268 if (voice_is_call_state_active(adev))
1269 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001270 }
1271
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001272 /* Disable current sound devices */
1273 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001274 disable_audio_route(adev, usecase);
1275 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001276 }
1277
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001278 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001279 disable_audio_route(adev, usecase);
1280 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001281 }
1282
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001283 /* Applicable only on the targets that has external modem.
1284 * New device information should be sent to modem before enabling
1285 * the devices to reduce in-call device switch time.
1286 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001287 if ((usecase->type == VOICE_CALL) &&
1288 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1289 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001290 status = platform_switch_voice_call_enable_device_config(adev->platform,
1291 out_snd_device,
1292 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001293 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001294
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001295 /* Enable new sound devices */
1296 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001297 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001298 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001299 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001300 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301 }
1302
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001303 if (in_snd_device != SND_DEVICE_NONE) {
1304 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001305 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001306 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001307
Eric Laurentb23d5282013-05-14 15:27:20 -07001308 if (usecase->type == VOICE_CALL)
1309 status = platform_switch_voice_call_device_post(adev->platform,
1310 out_snd_device,
1311 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001312
sangwoo170731f2013-06-08 15:36:36 +09001313 usecase->in_snd_device = in_snd_device;
1314 usecase->out_snd_device = out_snd_device;
1315
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001316 audio_extn_tfa_98xx_set_mode();
1317
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001318 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001319
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001320 /* Applicable only on the targets that has external modem.
1321 * Enable device command should be sent to modem only after
1322 * enabling voice call mixer controls
1323 */
vivek mehta765eb642015-08-07 19:46:06 -07001324 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001325 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1326 out_snd_device,
1327 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001328 /* Enable sidetone only if voice call already exists */
1329 if (voice_is_call_state_active(adev))
1330 voice_set_sidetone(adev, out_snd_device, true);
1331 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001333 return status;
1334}
1335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001336static int stop_input_stream(struct stream_in *in)
1337{
1338 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001339 struct audio_usecase *uc_info;
1340 struct audio_device *adev = in->dev;
1341
Eric Laurentc8400632013-02-14 19:04:54 -08001342 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343
Eric Laurent994a6932013-07-17 11:51:42 -07001344 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001345 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001346 uc_info = get_usecase_from_list(adev, in->usecase);
1347 if (uc_info == NULL) {
1348 ALOGE("%s: Could not find the usecase (%d) in the list",
1349 __func__, in->usecase);
1350 return -EINVAL;
1351 }
1352
vivek mehta781065c2017-04-04 12:55:01 -07001353 /* Close in-call recording streams */
1354 voice_check_and_stop_incall_rec_usecase(adev, in);
1355
Eric Laurent150dbfe2013-02-27 14:31:02 -08001356 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001357 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001358
1359 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001360 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001361
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001362 list_remove(&uc_info->list);
1363 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001364
Eric Laurent994a6932013-07-17 11:51:42 -07001365 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001366 return ret;
1367}
1368
1369int start_input_stream(struct stream_in *in)
1370{
1371 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001372 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 struct audio_usecase *uc_info;
1374 struct audio_device *adev = in->dev;
1375
Eric Laurent994a6932013-07-17 11:51:42 -07001376 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001377
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001378 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1379 return -EIO;
1380
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001381 if (in->card_status == CARD_STATUS_OFFLINE ||
1382 adev->card_status == CARD_STATUS_OFFLINE) {
1383 ALOGW("in->card_status or adev->card_status offline, try again");
1384 ret = -EAGAIN;
1385 goto error_config;
1386 }
1387
vivek mehta781065c2017-04-04 12:55:01 -07001388 /* Check if source matches incall recording usecase criteria */
1389 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1390 if (ret)
1391 goto error_config;
1392 else
1393 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1394
Eric Laurentb23d5282013-05-14 15:27:20 -07001395 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001396 if (in->pcm_device_id < 0) {
1397 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1398 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001399 ret = -EINVAL;
1400 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001401 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001402
1403 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1405 uc_info->id = in->usecase;
1406 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001407 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001408 uc_info->devices = in->device;
1409 uc_info->in_snd_device = SND_DEVICE_NONE;
1410 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001411
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001412 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001413
1414 audio_extn_perf_lock_acquire();
1415
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001416 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001417
Eric Laurent0e46adf2016-12-16 12:49:24 -08001418 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001419 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001420 ALOGE("%s: pcm stream not ready", __func__);
1421 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001422 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001423 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001424 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001425 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1426 goto error_open;
1427 }
1428 } else {
1429 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1430 unsigned int pcm_open_retry_count = 0;
1431
1432 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1433 flags |= PCM_MMAP | PCM_NOIRQ;
1434 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1435 } else if (in->realtime) {
1436 flags |= PCM_MMAP | PCM_NOIRQ;
1437 }
1438
1439 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1440 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1441
1442 while (1) {
1443 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1444 flags, &in->config);
1445 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1446 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1447 if (in->pcm != NULL) {
1448 pcm_close(in->pcm);
1449 in->pcm = NULL;
1450 }
1451 if (pcm_open_retry_count-- == 0) {
1452 ret = -EIO;
1453 goto error_open;
1454 }
1455 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1456 continue;
1457 }
1458 break;
1459 }
1460
1461 ALOGV("%s: pcm_prepare", __func__);
1462 ret = pcm_prepare(in->pcm);
1463 if (ret < 0) {
1464 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001465 pcm_close(in->pcm);
1466 in->pcm = NULL;
1467 goto error_open;
1468 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001469 if (in->realtime) {
1470 ret = pcm_start(in->pcm);
1471 if (ret < 0) {
1472 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1473 pcm_close(in->pcm);
1474 in->pcm = NULL;
1475 goto error_open;
1476 }
1477 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001478 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001479 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001480 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001481 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001482
Eric Laurent0e46adf2016-12-16 12:49:24 -08001483 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001484
1485error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001486 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001487 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001488
1489error_config:
1490 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001491 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001492 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493}
1494
Eric Laurenta1478072015-09-21 17:21:52 -07001495void lock_input_stream(struct stream_in *in)
1496{
1497 pthread_mutex_lock(&in->pre_lock);
1498 pthread_mutex_lock(&in->lock);
1499 pthread_mutex_unlock(&in->pre_lock);
1500}
1501
1502void lock_output_stream(struct stream_out *out)
1503{
1504 pthread_mutex_lock(&out->pre_lock);
1505 pthread_mutex_lock(&out->lock);
1506 pthread_mutex_unlock(&out->pre_lock);
1507}
1508
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001509/* must be called with out->lock locked */
1510static int send_offload_cmd_l(struct stream_out* out, int command)
1511{
1512 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1513
1514 ALOGVV("%s %d", __func__, command);
1515
1516 cmd->cmd = command;
1517 list_add_tail(&out->offload_cmd_list, &cmd->node);
1518 pthread_cond_signal(&out->offload_cond);
1519 return 0;
1520}
1521
1522/* must be called iwth out->lock locked */
1523static void stop_compressed_output_l(struct stream_out *out)
1524{
1525 out->offload_state = OFFLOAD_STATE_IDLE;
1526 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001527 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001528 if (out->compr != NULL) {
1529 compress_stop(out->compr);
1530 while (out->offload_thread_blocked) {
1531 pthread_cond_wait(&out->cond, &out->lock);
1532 }
1533 }
1534}
1535
1536static void *offload_thread_loop(void *context)
1537{
1538 struct stream_out *out = (struct stream_out *) context;
1539 struct listnode *item;
1540
1541 out->offload_state = OFFLOAD_STATE_IDLE;
1542 out->playback_started = 0;
1543
1544 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1545 set_sched_policy(0, SP_FOREGROUND);
1546 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1547
1548 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001549 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001550 for (;;) {
1551 struct offload_cmd *cmd = NULL;
1552 stream_callback_event_t event;
1553 bool send_callback = false;
1554
1555 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1556 __func__, list_empty(&out->offload_cmd_list),
1557 out->offload_state);
1558 if (list_empty(&out->offload_cmd_list)) {
1559 ALOGV("%s SLEEPING", __func__);
1560 pthread_cond_wait(&out->offload_cond, &out->lock);
1561 ALOGV("%s RUNNING", __func__);
1562 continue;
1563 }
1564
1565 item = list_head(&out->offload_cmd_list);
1566 cmd = node_to_item(item, struct offload_cmd, node);
1567 list_remove(item);
1568
1569 ALOGVV("%s STATE %d CMD %d out->compr %p",
1570 __func__, out->offload_state, cmd->cmd, out->compr);
1571
1572 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1573 free(cmd);
1574 break;
1575 }
1576
1577 if (out->compr == NULL) {
1578 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001579 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001580 pthread_cond_signal(&out->cond);
1581 continue;
1582 }
1583 out->offload_thread_blocked = true;
1584 pthread_mutex_unlock(&out->lock);
1585 send_callback = false;
1586 switch(cmd->cmd) {
1587 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1588 compress_wait(out->compr, -1);
1589 send_callback = true;
1590 event = STREAM_CBK_EVENT_WRITE_READY;
1591 break;
1592 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001593 compress_next_track(out->compr);
1594 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001595 send_callback = true;
1596 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001597 /* Resend the metadata for next iteration */
1598 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001599 break;
1600 case OFFLOAD_CMD_DRAIN:
1601 compress_drain(out->compr);
1602 send_callback = true;
1603 event = STREAM_CBK_EVENT_DRAIN_READY;
1604 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001605 case OFFLOAD_CMD_ERROR:
1606 send_callback = true;
1607 event = STREAM_CBK_EVENT_ERROR;
1608 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001609 default:
1610 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1611 break;
1612 }
Eric Laurenta1478072015-09-21 17:21:52 -07001613 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001614 out->offload_thread_blocked = false;
1615 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001616 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001617 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001618 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001619 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001620 free(cmd);
1621 }
1622
1623 pthread_cond_signal(&out->cond);
1624 while (!list_empty(&out->offload_cmd_list)) {
1625 item = list_head(&out->offload_cmd_list);
1626 list_remove(item);
1627 free(node_to_item(item, struct offload_cmd, node));
1628 }
1629 pthread_mutex_unlock(&out->lock);
1630
1631 return NULL;
1632}
1633
1634static int create_offload_callback_thread(struct stream_out *out)
1635{
1636 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1637 list_init(&out->offload_cmd_list);
1638 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1639 offload_thread_loop, out);
1640 return 0;
1641}
1642
1643static int destroy_offload_callback_thread(struct stream_out *out)
1644{
Eric Laurenta1478072015-09-21 17:21:52 -07001645 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001646 stop_compressed_output_l(out);
1647 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1648
1649 pthread_mutex_unlock(&out->lock);
1650 pthread_join(out->offload_thread, (void **) NULL);
1651 pthread_cond_destroy(&out->offload_cond);
1652
1653 return 0;
1654}
1655
Eric Laurent07eeafd2013-10-06 12:52:49 -07001656static bool allow_hdmi_channel_config(struct audio_device *adev)
1657{
1658 struct listnode *node;
1659 struct audio_usecase *usecase;
1660 bool ret = true;
1661
1662 list_for_each(node, &adev->usecase_list) {
1663 usecase = node_to_item(node, struct audio_usecase, list);
1664 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1665 /*
1666 * If voice call is already existing, do not proceed further to avoid
1667 * disabling/enabling both RX and TX devices, CSD calls, etc.
1668 * Once the voice call done, the HDMI channels can be configured to
1669 * max channels of remaining use cases.
1670 */
1671 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001672 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001673 __func__);
1674 ret = false;
1675 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001676 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1677 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001678 "no change in HDMI channels", __func__);
1679 ret = false;
1680 break;
1681 }
1682 }
1683 }
1684 return ret;
1685}
1686
1687static int check_and_set_hdmi_channels(struct audio_device *adev,
1688 unsigned int channels)
1689{
1690 struct listnode *node;
1691 struct audio_usecase *usecase;
1692
1693 /* Check if change in HDMI channel config is allowed */
1694 if (!allow_hdmi_channel_config(adev))
1695 return 0;
1696
1697 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001698 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001699 return 0;
1700 }
1701
1702 platform_set_hdmi_channels(adev->platform, channels);
1703 adev->cur_hdmi_channels = channels;
1704
1705 /*
1706 * Deroute all the playback streams routed to HDMI so that
1707 * the back end is deactivated. Note that backend will not
1708 * be deactivated if any one stream is connected to it.
1709 */
1710 list_for_each(node, &adev->usecase_list) {
1711 usecase = node_to_item(node, struct audio_usecase, list);
1712 if (usecase->type == PCM_PLAYBACK &&
1713 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001714 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001715 }
1716 }
1717
1718 /*
1719 * Enable all the streams disabled above. Now the HDMI backend
1720 * will be activated with new channel configuration
1721 */
1722 list_for_each(node, &adev->usecase_list) {
1723 usecase = node_to_item(node, struct audio_usecase, list);
1724 if (usecase->type == PCM_PLAYBACK &&
1725 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001726 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001727 }
1728 }
1729
1730 return 0;
1731}
1732
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001733static int stop_output_stream(struct stream_out *out)
1734{
1735 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001736 struct audio_usecase *uc_info;
1737 struct audio_device *adev = out->dev;
1738
Eric Laurent994a6932013-07-17 11:51:42 -07001739 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001740 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741 uc_info = get_usecase_from_list(adev, out->usecase);
1742 if (uc_info == NULL) {
1743 ALOGE("%s: Could not find the usecase (%d) in the list",
1744 __func__, out->usecase);
1745 return -EINVAL;
1746 }
1747
Haynes Mathew George41f86652014-06-17 14:22:15 -07001748 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1749 if (adev->visualizer_stop_output != NULL)
1750 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1751 if (adev->offload_effects_stop_output != NULL)
1752 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1753 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001754
Eric Laurent150dbfe2013-02-27 14:31:02 -08001755 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001756 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001757
1758 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001759 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001760
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001761 list_remove(&uc_info->list);
1762 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763
Eric Laurent0499d4f2014-08-25 22:39:29 -05001764 audio_extn_extspk_update(adev->extspk);
1765
Eric Laurent07eeafd2013-10-06 12:52:49 -07001766 /* Must be called after removing the usecase from list */
1767 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1768 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1769
Eric Laurent994a6932013-07-17 11:51:42 -07001770 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771 return ret;
1772}
1773
1774int start_output_stream(struct stream_out *out)
1775{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777 struct audio_usecase *uc_info;
1778 struct audio_device *adev = out->dev;
1779
Eric Laurent994a6932013-07-17 11:51:42 -07001780 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001781 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001782
1783 if (out->card_status == CARD_STATUS_OFFLINE ||
1784 adev->card_status == CARD_STATUS_OFFLINE) {
1785 ALOGW("out->card_status or adev->card_status offline, try again");
1786 ret = -EAGAIN;
1787 goto error_config;
1788 }
1789
Eric Laurentb23d5282013-05-14 15:27:20 -07001790 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 if (out->pcm_device_id < 0) {
1792 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1793 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001794 ret = -EINVAL;
1795 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 }
1797
1798 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1799 uc_info->id = out->usecase;
1800 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001801 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001802 uc_info->devices = out->devices;
1803 uc_info->in_snd_device = SND_DEVICE_NONE;
1804 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001805
Eric Laurent07eeafd2013-10-06 12:52:49 -07001806 /* This must be called before adding this usecase to the list */
1807 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1808 check_and_set_hdmi_channels(adev, out->config.channels);
1809
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001810 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001812 audio_extn_perf_lock_acquire();
1813
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001814 select_devices(adev, out->usecase);
1815
Eric Laurent0499d4f2014-08-25 22:39:29 -05001816 audio_extn_extspk_update(adev->extspk);
1817
Andy Hung31aca912014-03-20 17:14:59 -07001818 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001819 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001820 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1821 out->pcm = NULL;
1822 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1823 COMPRESS_IN, &out->compr_config);
1824 if (out->compr && !is_compress_ready(out->compr)) {
1825 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1826 compress_close(out->compr);
1827 out->compr = NULL;
1828 ret = -EIO;
1829 goto error_open;
1830 }
1831 if (out->offload_callback)
1832 compress_nonblock(out->compr, out->non_blocking);
1833
1834 if (adev->visualizer_start_output != NULL)
1835 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1836 if (adev->offload_effects_start_output != NULL)
1837 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1838 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001839 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001840 ALOGE("%s: pcm stream not ready", __func__);
1841 goto error_open;
1842 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001843 ret = pcm_start(out->pcm);
1844 if (ret < 0) {
1845 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1846 goto error_open;
1847 }
1848 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001849 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001850 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001851
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001852 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1853 flags |= PCM_MMAP | PCM_NOIRQ;
1854 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001855 } else if (out->realtime) {
1856 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001857 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001858
1859 while (1) {
1860 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1861 flags, &out->config);
1862 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1863 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1864 if (out->pcm != NULL) {
1865 pcm_close(out->pcm);
1866 out->pcm = NULL;
1867 }
1868 if (pcm_open_retry_count-- == 0) {
1869 ret = -EIO;
1870 goto error_open;
1871 }
1872 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1873 continue;
1874 }
1875 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001876 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001877 ALOGV("%s: pcm_prepare", __func__);
1878 if (pcm_is_ready(out->pcm)) {
1879 ret = pcm_prepare(out->pcm);
1880 if (ret < 0) {
1881 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1882 pcm_close(out->pcm);
1883 out->pcm = NULL;
1884 goto error_open;
1885 }
1886 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001887 if (out->realtime) {
1888 ret = pcm_start(out->pcm);
1889 if (ret < 0) {
1890 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1891 pcm_close(out->pcm);
1892 out->pcm = NULL;
1893 goto error_open;
1894 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001895 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001896 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001897 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001898 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001899 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001900 audio_extn_utils_send_app_type_gain(out->dev,
1901 out->app_type_cfg.app_type,
1902 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001903
1904 // consider a scenario where on pause lower layers are tear down.
1905 // so on resume, swap mixer control need to be sent only when
1906 // backend is active, hence rather than sending from enable device
1907 // sending it from start of streamtream
1908
1909 platform_set_swap_channels(adev, true);
1910
Eric Laurent994a6932013-07-17 11:51:42 -07001911 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001912 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001913error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001914 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001916error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001917 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918}
1919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920static int check_input_parameters(uint32_t sample_rate,
1921 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001922 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001924 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1925 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001926 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1927 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001928 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1929 return -EINVAL;
1930 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931
Eric Laurent74b55762017-07-09 17:04:53 -07001932 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1933 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001934 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001935 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001936 return -EINVAL;
1937 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938
1939 switch (sample_rate) {
1940 case 8000:
1941 case 11025:
1942 case 12000:
1943 case 16000:
1944 case 22050:
1945 case 24000:
1946 case 32000:
1947 case 44100:
1948 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001949 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950 break;
1951 default:
vivek mehtadae44712015-07-27 14:13:18 -07001952 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 return -EINVAL;
1954 }
1955
1956 return 0;
1957}
1958
vivek mehtaa68fea62017-06-08 19:04:02 -07001959static size_t get_stream_buffer_size(size_t duration_ms,
1960 uint32_t sample_rate,
1961 audio_format_t format,
1962 int channel_count,
1963 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964{
1965 size_t size = 0;
1966
vivek mehtaa68fea62017-06-08 19:04:02 -07001967 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001968 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001969 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001970
1971 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972
Glenn Kasten4f993392014-05-14 07:30:48 -07001973 /* make sure the size is multiple of 32 bytes
1974 * At 48 kHz mono 16-bit PCM:
1975 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1976 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1977 */
1978 size += 0x1f;
1979 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001980
1981 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982}
1983
1984static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1985{
1986 struct stream_out *out = (struct stream_out *)stream;
1987
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001988 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989}
1990
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001991static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001992{
1993 return -ENOSYS;
1994}
1995
1996static size_t out_get_buffer_size(const struct audio_stream *stream)
1997{
1998 struct stream_out *out = (struct stream_out *)stream;
1999
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002000 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2001 return out->compr_config.fragment_size;
2002 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002003 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002004 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005}
2006
2007static uint32_t out_get_channels(const struct audio_stream *stream)
2008{
2009 struct stream_out *out = (struct stream_out *)stream;
2010
2011 return out->channel_mask;
2012}
2013
2014static audio_format_t out_get_format(const struct audio_stream *stream)
2015{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002016 struct stream_out *out = (struct stream_out *)stream;
2017
2018 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019}
2020
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002021static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022{
2023 return -ENOSYS;
2024}
2025
2026static int out_standby(struct audio_stream *stream)
2027{
2028 struct stream_out *out = (struct stream_out *)stream;
2029 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002030 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031
Eric Laurent994a6932013-07-17 11:51:42 -07002032 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002033 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034
Eric Laurenta1478072015-09-21 17:21:52 -07002035 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002036 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002037 if (adev->adm_deregister_stream)
2038 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002039 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002041 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2042 if (out->pcm) {
2043 pcm_close(out->pcm);
2044 out->pcm = NULL;
2045 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002046 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002047 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002048 out->playback_started = false;
2049 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002050 } else {
2051 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002052 out->gapless_mdata.encoder_delay = 0;
2053 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002054 if (out->compr != NULL) {
2055 compress_close(out->compr);
2056 out->compr = NULL;
2057 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002058 }
Phil Burkbc991042017-02-24 08:06:44 -08002059 if (do_stop) {
2060 stop_output_stream(out);
2061 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002062 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 }
2064 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002065 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066 return 0;
2067}
2068
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002069static int out_on_error(struct audio_stream *stream)
2070{
2071 struct stream_out *out = (struct stream_out *)stream;
2072 struct audio_device *adev = out->dev;
2073 bool do_standby = false;
2074
2075 lock_output_stream(out);
2076 if (!out->standby) {
2077 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2078 stop_compressed_output_l(out);
2079 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2080 } else
2081 do_standby = true;
2082 }
2083 pthread_mutex_unlock(&out->lock);
2084
2085 if (do_standby)
2086 return out_standby(&out->stream.common);
2087
2088 return 0;
2089}
2090
Andy Hung7401c7c2016-09-21 12:41:21 -07002091static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092{
Andy Hung7401c7c2016-09-21 12:41:21 -07002093 struct stream_out *out = (struct stream_out *)stream;
2094
2095 // We try to get the lock for consistency,
2096 // but it isn't necessary for these variables.
2097 // If we're not in standby, we may be blocked on a write.
2098 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2099 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2100 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2101
2102 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002103 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002104 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002105
2106 // dump error info
2107 (void)error_log_dump(
2108 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002110 return 0;
2111}
2112
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002113static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2114{
2115 int ret = 0;
2116 char value[32];
2117 struct compr_gapless_mdata tmp_mdata;
2118
2119 if (!out || !parms) {
2120 return -EINVAL;
2121 }
2122
2123 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2124 if (ret >= 0) {
2125 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2126 } else {
2127 return -EINVAL;
2128 }
2129
2130 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2131 if (ret >= 0) {
2132 tmp_mdata.encoder_padding = atoi(value);
2133 } else {
2134 return -EINVAL;
2135 }
2136
2137 out->gapless_mdata = tmp_mdata;
2138 out->send_new_metadata = 1;
2139 ALOGV("%s new encoder delay %u and padding %u", __func__,
2140 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2141
2142 return 0;
2143}
2144
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002145static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2146{
2147 return out == adev->primary_output || out == adev->voice_tx_output;
2148}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2151{
2152 struct stream_out *out = (struct stream_out *)stream;
2153 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002154 struct audio_usecase *usecase;
2155 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156 struct str_parms *parms;
2157 char value[32];
2158 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002159 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002160 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161
Eric Laurent2e140aa2016-06-30 17:14:46 -07002162 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002163 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164 parms = str_parms_create_str(kvpairs);
2165 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2166 if (ret >= 0) {
2167 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002168 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002169 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002171 /*
2172 * When HDMI cable is unplugged the music playback is paused and
2173 * the policy manager sends routing=0. But the audioflinger
2174 * continues to write data until standby time (3sec).
2175 * As the HDMI core is turned off, the write gets blocked.
2176 * Avoid this by routing audio to speaker until standby.
2177 */
2178 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2179 val == AUDIO_DEVICE_NONE) {
2180 val = AUDIO_DEVICE_OUT_SPEAKER;
2181 }
2182
2183 /*
2184 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002185 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002186 * the select_devices(). But how do we undo this?
2187 *
2188 * For example, music playback is active on headset (deep-buffer usecase)
2189 * and if we go to ringtones and select a ringtone, low-latency usecase
2190 * will be started on headset+speaker. As we can't enable headset+speaker
2191 * and headset devices at the same time, select_devices() switches the music
2192 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2193 * So when the ringtone playback is completed, how do we undo the same?
2194 *
2195 * We are relying on the out_set_parameters() call on deep-buffer output,
2196 * once the ringtone playback is ended.
2197 * NOTE: We should not check if the current devices are same as new devices.
2198 * Because select_devices() must be called to switch back the music
2199 * playback to headset.
2200 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002201 audio_devices_t new_dev = val;
2202 if (new_dev != AUDIO_DEVICE_NONE) {
2203 bool same_dev = out->devices == new_dev;
2204 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002205
Eric Laurenta7657192014-10-09 21:09:33 -07002206 if (output_drives_call(adev, out)) {
2207 if (!voice_is_in_call(adev)) {
2208 if (adev->mode == AUDIO_MODE_IN_CALL) {
2209 adev->current_call_output = out;
2210 ret = voice_start_call(adev);
2211 }
2212 } else {
2213 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002214 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002215 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002216 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002217
2218 if (!out->standby) {
2219 if (!same_dev) {
2220 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002221 // inform adm before actual routing to prevent glitches.
2222 if (adev->adm_on_routing_change) {
2223 adev->adm_on_routing_change(adev->adm_data,
2224 out->handle);
2225 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002226 }
2227 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002228 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002229
2230 // on device switch force swap, lower functions will make sure
2231 // to check if swap is allowed or not.
2232
2233 if (!same_dev)
2234 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002235 }
2236
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002237 }
2238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002240 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002241
2242 /*handles device and call state changes*/
2243 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002245
2246 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2247 parse_compress_metadata(out, parms);
2248 }
2249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002251 ALOGV("%s: exit: code(%d)", __func__, status);
2252 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253}
2254
Haynes Mathew George569b7482017-05-08 14:44:27 -07002255static bool stream_get_parameter_channels(struct str_parms *query,
2256 struct str_parms *reply,
2257 audio_channel_mask_t *supported_channel_masks) {
2258 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002261 size_t i, j;
2262
2263 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2264 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265 value[0] = '\0';
2266 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002267 while (supported_channel_masks[i] != 0) {
2268 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2269 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 if (!first) {
2271 strcat(value, "|");
2272 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002273 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002274 first = false;
2275 break;
2276 }
2277 }
2278 i++;
2279 }
2280 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002281 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002282 return ret >= 0;
2283}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002284
Haynes Mathew George569b7482017-05-08 14:44:27 -07002285static bool stream_get_parameter_formats(struct str_parms *query,
2286 struct str_parms *reply,
2287 audio_format_t *supported_formats) {
2288 int ret = -1;
2289 char value[256];
2290 int i;
2291
2292 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2293 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002294 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002295 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002296 case AUDIO_FORMAT_PCM_16_BIT:
2297 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2298 break;
2299 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2300 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2301 break;
2302 case AUDIO_FORMAT_PCM_32_BIT:
2303 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2304 break;
2305 default:
2306 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002307 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002308 break;
2309 }
2310 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002311 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002312 return ret >= 0;
2313}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002314
Haynes Mathew George569b7482017-05-08 14:44:27 -07002315static bool stream_get_parameter_rates(struct str_parms *query,
2316 struct str_parms *reply,
2317 uint32_t *supported_sample_rates) {
2318
2319 int i;
2320 char value[256];
2321 int ret = -1;
2322 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2323 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002324 value[0] = '\0';
2325 i=0;
2326 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002327 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002328 int avail = sizeof(value) - cursor;
2329 ret = snprintf(value + cursor, avail, "%s%d",
2330 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002331 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002332 if (ret < 0 || ret >= avail) {
2333 // if cursor is at the last element of the array
2334 // overwrite with \0 is duplicate work as
2335 // snprintf already put a \0 in place.
2336 // else
2337 // we had space to write the '|' at value[cursor]
2338 // (which will be overwritten) or no space to fill
2339 // the first element (=> cursor == 0)
2340 value[cursor] = '\0';
2341 break;
2342 }
2343 cursor += ret;
2344 ++i;
2345 }
2346 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2347 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002348 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002349 return ret >= 0;
2350}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002351
Haynes Mathew George569b7482017-05-08 14:44:27 -07002352static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2353{
2354 struct stream_out *out = (struct stream_out *)stream;
2355 struct str_parms *query = str_parms_create_str(keys);
2356 char *str;
2357 struct str_parms *reply = str_parms_create();
2358 bool replied = false;
2359 ALOGV("%s: enter: keys - %s", __func__, keys);
2360
2361 replied |= stream_get_parameter_channels(query, reply,
2362 &out->supported_channel_masks[0]);
2363 replied |= stream_get_parameter_formats(query, reply,
2364 &out->supported_formats[0]);
2365 replied |= stream_get_parameter_rates(query, reply,
2366 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002367 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002368 str = str_parms_to_str(reply);
2369 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002370 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002371 }
2372 str_parms_destroy(query);
2373 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002374 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375 return str;
2376}
2377
2378static uint32_t out_get_latency(const struct audio_stream_out *stream)
2379{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002380 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381 struct stream_out *out = (struct stream_out *)stream;
2382
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2384 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002385 else if ((out->realtime) ||
2386 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002387 // since the buffer won't be filled up faster than realtime,
2388 // return a smaller number
2389 period_ms = (out->af_period_multiplier * out->config.period_size *
2390 1000) / (out->config.rate);
2391 hw_delay = platform_render_latency(out->usecase)/1000;
2392 return period_ms + hw_delay;
2393 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002394
2395 return (out->config.period_count * out->config.period_size * 1000) /
2396 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397}
2398
2399static int out_set_volume(struct audio_stream_out *stream, float left,
2400 float right)
2401{
Eric Laurenta9024de2013-04-04 09:19:12 -07002402 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403 int volume[2];
2404
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002405 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002406 /* only take left channel into account: the API is for stereo anyway */
2407 out->muted = (left == 0.0f);
2408 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002409 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2410 const char *mixer_ctl_name = "Compress Playback Volume";
2411 struct audio_device *adev = out->dev;
2412 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2414 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002415 /* try with the control based on device id */
2416 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2417 PCM_PLAYBACK);
2418 char ctl_name[128] = {0};
2419 snprintf(ctl_name, sizeof(ctl_name),
2420 "Compress Playback %d Volume", pcm_device_id);
2421 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2422 if (!ctl) {
2423 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2424 return -EINVAL;
2425 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002426 }
2427 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2428 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2429 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2430 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002431 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002432 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2433 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2434 if (!out->standby) {
2435 // if in standby, cached volume will be sent after stream is opened
2436 audio_extn_utils_send_app_type_gain(out->dev,
2437 out->app_type_cfg.app_type,
2438 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002439 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002440 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002441 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002442
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443 return -ENOSYS;
2444}
2445
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002446// note: this call is safe only if the stream_cb is
2447// removed first in close_output_stream (as is done now).
2448static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2449{
2450 if (!stream || !parms)
2451 return;
2452
2453 struct stream_out *out = (struct stream_out *)stream;
2454 struct audio_device *adev = out->dev;
2455
2456 card_status_t status;
2457 int card;
2458 if (parse_snd_card_status(parms, &card, &status) < 0)
2459 return;
2460
2461 pthread_mutex_lock(&adev->lock);
2462 bool valid_cb = (card == adev->snd_card);
2463 pthread_mutex_unlock(&adev->lock);
2464
2465 if (!valid_cb)
2466 return;
2467
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002468 lock_output_stream(out);
2469 if (out->card_status != status)
2470 out->card_status = status;
2471 pthread_mutex_unlock(&out->lock);
2472
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002473 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2474 use_case_table[out->usecase],
2475 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2476
2477 if (status == CARD_STATUS_OFFLINE)
2478 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002479
2480 return;
2481}
2482
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002483#ifdef NO_AUDIO_OUT
2484static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002485 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002486{
2487 struct stream_out *out = (struct stream_out *)stream;
2488
2489 /* No Output device supported other than BT for playback.
2490 * Sleep for the amount of buffer duration
2491 */
Eric Laurenta1478072015-09-21 17:21:52 -07002492 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002493 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2494 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002495 out_get_sample_rate(&out->stream.common));
2496 pthread_mutex_unlock(&out->lock);
2497 return bytes;
2498}
2499#endif
2500
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2502 size_t bytes)
2503{
2504 struct stream_out *out = (struct stream_out *)stream;
2505 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002506 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002507 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508
Eric Laurenta1478072015-09-21 17:21:52 -07002509 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002510 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002511 const size_t frame_size = audio_stream_out_frame_size(stream);
2512 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002513
Eric Laurent0e46adf2016-12-16 12:49:24 -08002514 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2515 error_code = ERROR_CODE_WRITE;
2516 goto exit;
2517 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002519 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002520 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002522 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002523 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002525 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 goto exit;
2527 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002528
2529 if (last_known_cal_step != -1) {
2530 ALOGD("%s: retry previous failed cal level set", __func__);
2531 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2532 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002535 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002536 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002537 if (out->send_new_metadata) {
2538 ALOGVV("send new gapless metadata");
2539 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2540 out->send_new_metadata = 0;
2541 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002542 unsigned int avail;
2543 struct timespec tstamp;
2544 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2545 /* Do not limit write size if the available frames count is unknown */
2546 if (ret != 0) {
2547 avail = bytes;
2548 }
2549 if (avail == 0) {
2550 ret = 0;
2551 } else {
2552 if (avail > bytes) {
2553 avail = bytes;
2554 }
2555 ret = compress_write(out->compr, buffer, avail);
2556 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2557 __func__, avail, ret);
2558 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002559
Eric Laurent6e895242013-09-05 16:10:57 -07002560 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002561 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2562 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002563 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002564 compress_start(out->compr);
2565 out->playback_started = 1;
2566 out->offload_state = OFFLOAD_STATE_PLAYING;
2567 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002568 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002569 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002570 } else {
2571 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002572 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002573 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002574 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002575 return ret;
2576 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002577 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002578 if (out->pcm) {
2579 if (out->muted)
2580 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002581
Eric Laurent0e46adf2016-12-16 12:49:24 -08002582 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002583
Haynes Mathew George03c40102016-01-29 17:57:48 -08002584 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2585 out->config.rate;
2586 request_out_focus(out, ns);
2587
2588 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2589 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002590 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002591 else
2592 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002593
Haynes Mathew George03c40102016-01-29 17:57:48 -08002594 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002595 } else {
2596 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002597 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598 }
2599
2600exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002601 // For PCM we always consume the buffer and return #bytes regardless of ret.
2602 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002603 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002604 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002605 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002606
Andy Hung7401c7c2016-09-21 12:41:21 -07002607 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002608 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002609 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2610 ALOGE_IF(out->pcm != NULL,
2611 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002612 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002613 // usleep not guaranteed for values over 1 second but we don't limit here.
2614 }
2615 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617 pthread_mutex_unlock(&out->lock);
2618
2619 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002620 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002621 if (sleeptime_us != 0)
2622 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623 }
2624 return bytes;
2625}
2626
2627static int out_get_render_position(const struct audio_stream_out *stream,
2628 uint32_t *dsp_frames)
2629{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002630 struct stream_out *out = (struct stream_out *)stream;
2631 *dsp_frames = 0;
2632 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002633 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002634 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002635 unsigned long frames = 0;
2636 // TODO: check return value
2637 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2638 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002639 ALOGVV("%s rendered frames %d sample_rate %d",
2640 __func__, *dsp_frames, out->sample_rate);
2641 }
2642 pthread_mutex_unlock(&out->lock);
2643 return 0;
2644 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002645 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646}
2647
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002648static int out_add_audio_effect(const struct audio_stream *stream __unused,
2649 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650{
2651 return 0;
2652}
2653
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002654static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2655 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656{
2657 return 0;
2658}
2659
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002660static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2661 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002663 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664}
2665
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002666static int out_get_presentation_position(const struct audio_stream_out *stream,
2667 uint64_t *frames, struct timespec *timestamp)
2668{
2669 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002670 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002671 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002672
Eric Laurenta1478072015-09-21 17:21:52 -07002673 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002674
Eric Laurent949a0892013-09-20 09:20:13 -07002675 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2676 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002677 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002678 compress_get_tstamp(out->compr, &dsp_frames,
2679 &out->sample_rate);
2680 ALOGVV("%s rendered frames %ld sample_rate %d",
2681 __func__, dsp_frames, out->sample_rate);
2682 *frames = dsp_frames;
2683 ret = 0;
2684 /* this is the best we can do */
2685 clock_gettime(CLOCK_MONOTONIC, timestamp);
2686 }
2687 } else {
2688 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002689 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002690 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2691 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002692 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002693 // This adjustment accounts for buffering after app processor.
2694 // It is based on estimated DSP latency per use case, rather than exact.
2695 signed_frames -=
2696 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2697
Eric Laurent949a0892013-09-20 09:20:13 -07002698 // It would be unusual for this value to be negative, but check just in case ...
2699 if (signed_frames >= 0) {
2700 *frames = signed_frames;
2701 ret = 0;
2702 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002703 }
2704 }
2705 }
2706
2707 pthread_mutex_unlock(&out->lock);
2708
2709 return ret;
2710}
2711
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002712static int out_set_callback(struct audio_stream_out *stream,
2713 stream_callback_t callback, void *cookie)
2714{
2715 struct stream_out *out = (struct stream_out *)stream;
2716
2717 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002718 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002719 out->offload_callback = callback;
2720 out->offload_cookie = cookie;
2721 pthread_mutex_unlock(&out->lock);
2722 return 0;
2723}
2724
2725static int out_pause(struct audio_stream_out* stream)
2726{
2727 struct stream_out *out = (struct stream_out *)stream;
2728 int status = -ENOSYS;
2729 ALOGV("%s", __func__);
2730 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002731 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002732 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2733 status = compress_pause(out->compr);
2734 out->offload_state = OFFLOAD_STATE_PAUSED;
2735 }
2736 pthread_mutex_unlock(&out->lock);
2737 }
2738 return status;
2739}
2740
2741static int out_resume(struct audio_stream_out* stream)
2742{
2743 struct stream_out *out = (struct stream_out *)stream;
2744 int status = -ENOSYS;
2745 ALOGV("%s", __func__);
2746 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2747 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002748 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002749 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2750 status = compress_resume(out->compr);
2751 out->offload_state = OFFLOAD_STATE_PLAYING;
2752 }
2753 pthread_mutex_unlock(&out->lock);
2754 }
2755 return status;
2756}
2757
2758static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2759{
2760 struct stream_out *out = (struct stream_out *)stream;
2761 int status = -ENOSYS;
2762 ALOGV("%s", __func__);
2763 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002764 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002765 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2766 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2767 else
2768 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2769 pthread_mutex_unlock(&out->lock);
2770 }
2771 return status;
2772}
2773
2774static int out_flush(struct audio_stream_out* stream)
2775{
2776 struct stream_out *out = (struct stream_out *)stream;
2777 ALOGV("%s", __func__);
2778 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002779 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002780 stop_compressed_output_l(out);
2781 pthread_mutex_unlock(&out->lock);
2782 return 0;
2783 }
2784 return -ENOSYS;
2785}
2786
Eric Laurent0e46adf2016-12-16 12:49:24 -08002787static int out_stop(const struct audio_stream_out* stream)
2788{
2789 struct stream_out *out = (struct stream_out *)stream;
2790 struct audio_device *adev = out->dev;
2791 int ret = -ENOSYS;
2792
2793 ALOGV("%s", __func__);
2794 pthread_mutex_lock(&adev->lock);
2795 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2796 out->playback_started && out->pcm != NULL) {
2797 pcm_stop(out->pcm);
2798 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002799 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002800 }
2801 pthread_mutex_unlock(&adev->lock);
2802 return ret;
2803}
2804
2805static int out_start(const struct audio_stream_out* stream)
2806{
2807 struct stream_out *out = (struct stream_out *)stream;
2808 struct audio_device *adev = out->dev;
2809 int ret = -ENOSYS;
2810
2811 ALOGV("%s", __func__);
2812 pthread_mutex_lock(&adev->lock);
2813 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2814 !out->playback_started && out->pcm != NULL) {
2815 ret = start_output_stream(out);
2816 if (ret == 0) {
2817 out->playback_started = true;
2818 }
2819 }
2820 pthread_mutex_unlock(&adev->lock);
2821 return ret;
2822}
2823
Phil Burkbc991042017-02-24 08:06:44 -08002824/*
2825 * Modify config->period_count based on min_size_frames
2826 */
2827static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2828{
2829 int periodCountRequested = (min_size_frames + config->period_size - 1)
2830 / config->period_size;
2831 int periodCount = MMAP_PERIOD_COUNT_MIN;
2832
2833 ALOGV("%s original config.period_size = %d config.period_count = %d",
2834 __func__, config->period_size, config->period_count);
2835
2836 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2837 periodCount *= 2;
2838 }
2839 config->period_count = periodCount;
2840
2841 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2842}
2843
Eric Laurent0e46adf2016-12-16 12:49:24 -08002844static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2845 int32_t min_size_frames,
2846 struct audio_mmap_buffer_info *info)
2847{
2848 struct stream_out *out = (struct stream_out *)stream;
2849 struct audio_device *adev = out->dev;
2850 int ret = 0;
2851 unsigned int offset1;
2852 unsigned int frames1;
2853 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002854 uint32_t mmap_size;
2855 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002856
2857 ALOGV("%s", __func__);
2858 pthread_mutex_lock(&adev->lock);
2859
2860 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002861 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002862 ret = -EINVAL;
2863 goto exit;
2864 }
2865 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002866 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002867 ret = -ENOSYS;
2868 goto exit;
2869 }
2870 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2871 if (out->pcm_device_id < 0) {
2872 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2873 __func__, out->pcm_device_id, out->usecase);
2874 ret = -EINVAL;
2875 goto exit;
2876 }
Phil Burkbc991042017-02-24 08:06:44 -08002877
2878 adjust_mmap_period_count(&out->config, min_size_frames);
2879
Eric Laurent0e46adf2016-12-16 12:49:24 -08002880 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2881 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2882 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2883 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2884 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2885 step = "open";
2886 ret = -ENODEV;
2887 goto exit;
2888 }
2889 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2890 if (ret < 0) {
2891 step = "begin";
2892 goto exit;
2893 }
2894 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002895 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002896 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002897 ret = platform_get_mmap_data_fd(adev->platform,
2898 out->pcm_device_id, 0 /*playback*/,
2899 &info->shared_memory_fd,
2900 &mmap_size);
2901 if (ret < 0) {
2902 // Fall back to non exclusive mode
2903 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2904 } else {
2905 if (mmap_size < buffer_size) {
2906 step = "mmap";
2907 goto exit;
2908 }
2909 // FIXME: indicate exclusive mode support by returning a negative buffer size
2910 info->buffer_size_frames *= -1;
2911 }
2912 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002913
2914 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2915 if (ret < 0) {
2916 step = "commit";
2917 goto exit;
2918 }
Phil Burkbc991042017-02-24 08:06:44 -08002919
2920 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002921 ret = 0;
2922
2923 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2924 __func__, info->shared_memory_address, info->buffer_size_frames);
2925
2926exit:
2927 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002928 if (out->pcm == NULL) {
2929 ALOGE("%s: %s - %d", __func__, step, ret);
2930 } else {
2931 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002932 pcm_close(out->pcm);
2933 out->pcm = NULL;
2934 }
2935 }
2936 pthread_mutex_unlock(&adev->lock);
2937 return ret;
2938}
2939
2940static int out_get_mmap_position(const struct audio_stream_out *stream,
2941 struct audio_mmap_position *position)
2942{
2943 struct stream_out *out = (struct stream_out *)stream;
2944 ALOGVV("%s", __func__);
2945 if (position == NULL) {
2946 return -EINVAL;
2947 }
2948 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2949 return -ENOSYS;
2950 }
2951 if (out->pcm == NULL) {
2952 return -ENOSYS;
2953 }
2954
2955 struct timespec ts = { 0, 0 };
2956 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2957 if (ret < 0) {
2958 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2959 return ret;
2960 }
Andy Hungfc044e12017-03-20 09:24:22 -07002961 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002962 return 0;
2963}
2964
2965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002966/** audio_stream_in implementation **/
2967static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2968{
2969 struct stream_in *in = (struct stream_in *)stream;
2970
2971 return in->config.rate;
2972}
2973
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002974static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002975{
2976 return -ENOSYS;
2977}
2978
2979static size_t in_get_buffer_size(const struct audio_stream *stream)
2980{
2981 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002982 return in->config.period_size * in->af_period_multiplier *
2983 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984}
2985
2986static uint32_t in_get_channels(const struct audio_stream *stream)
2987{
2988 struct stream_in *in = (struct stream_in *)stream;
2989
2990 return in->channel_mask;
2991}
2992
vivek mehta4ed66e62016-04-15 23:33:34 -07002993static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994{
vivek mehta4ed66e62016-04-15 23:33:34 -07002995 struct stream_in *in = (struct stream_in *)stream;
2996 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997}
2998
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002999static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003000{
3001 return -ENOSYS;
3002}
3003
3004static int in_standby(struct audio_stream *stream)
3005{
3006 struct stream_in *in = (struct stream_in *)stream;
3007 struct audio_device *adev = in->dev;
3008 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003009 bool do_stop = true;
3010
Eric Laurent994a6932013-07-17 11:51:42 -07003011 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003012
3013 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003014
3015 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003016 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003017 audio_extn_sound_trigger_stop_lab(in);
3018 in->standby = true;
3019 }
3020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003022 if (adev->adm_deregister_stream)
3023 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3024
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003025 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003027 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003028 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003029 in->capture_started = false;
3030 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003031 if (in->pcm) {
3032 pcm_close(in->pcm);
3033 in->pcm = NULL;
3034 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003035 adev->enable_voicerx = false;
3036 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003037 if (do_stop) {
3038 status = stop_input_stream(in);
3039 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003040 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 }
3042 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003043 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 return status;
3045}
3046
Andy Hungd13f0d32017-06-12 13:58:37 -07003047static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048{
Andy Hungd13f0d32017-06-12 13:58:37 -07003049 struct stream_in *in = (struct stream_in *)stream;
3050
3051 // We try to get the lock for consistency,
3052 // but it isn't necessary for these variables.
3053 // If we're not in standby, we may be blocked on a read.
3054 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3055 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3056 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3057 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3058
3059 if (locked) {
3060 pthread_mutex_unlock(&in->lock);
3061 }
3062
3063 // dump error info
3064 (void)error_log_dump(
3065 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 return 0;
3067}
3068
3069static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3070{
3071 struct stream_in *in = (struct stream_in *)stream;
3072 struct audio_device *adev = in->dev;
3073 struct str_parms *parms;
3074 char *str;
3075 char value[32];
3076 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003077 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078
Eric Laurent994a6932013-07-17 11:51:42 -07003079 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 parms = str_parms_create_str(kvpairs);
3081
3082 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3083
Eric Laurenta1478072015-09-21 17:21:52 -07003084 lock_input_stream(in);
3085
Eric Laurent150dbfe2013-02-27 14:31:02 -08003086 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087 if (ret >= 0) {
3088 val = atoi(value);
3089 /* no audio source uses val == 0 */
3090 if ((in->source != val) && (val != 0)) {
3091 in->source = val;
3092 }
3093 }
3094
3095 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097 if (ret >= 0) {
3098 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003099 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100 in->device = val;
3101 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003102 if (!in->standby) {
3103 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003104 // inform adm before actual routing to prevent glitches.
3105 if (adev->adm_on_routing_change) {
3106 adev->adm_on_routing_change(adev->adm_data,
3107 in->capture_handle);
3108 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003109 select_devices(adev, in->usecase);
3110 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 }
3112 }
3113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003114 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003115 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003116
3117 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003118 ALOGV("%s: exit: status(%d)", __func__, status);
3119 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120}
3121
Haynes Mathew George569b7482017-05-08 14:44:27 -07003122static char* in_get_parameters(const struct audio_stream *stream,
3123 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003124{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003125 struct stream_in *in = (struct stream_in *)stream;
3126 struct str_parms *query = str_parms_create_str(keys);
3127 char *str;
3128 struct str_parms *reply = str_parms_create();
3129 bool replied = false;
3130
3131 ALOGV("%s: enter: keys - %s", __func__, keys);
3132 replied |= stream_get_parameter_channels(query, reply,
3133 &in->supported_channel_masks[0]);
3134 replied |= stream_get_parameter_formats(query, reply,
3135 &in->supported_formats[0]);
3136 replied |= stream_get_parameter_rates(query, reply,
3137 &in->supported_sample_rates[0]);
3138 if (replied) {
3139 str = str_parms_to_str(reply);
3140 } else {
3141 str = strdup(keys);
3142 }
3143 str_parms_destroy(query);
3144 str_parms_destroy(reply);
3145 ALOGV("%s: exit: returns - %s", __func__, str);
3146 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003147}
3148
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003149static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003151 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152}
3153
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003154static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3155{
3156 if (!stream || !parms)
3157 return;
3158
3159 struct stream_in *in = (struct stream_in *)stream;
3160 struct audio_device *adev = in->dev;
3161
3162 card_status_t status;
3163 int card;
3164 if (parse_snd_card_status(parms, &card, &status) < 0)
3165 return;
3166
3167 pthread_mutex_lock(&adev->lock);
3168 bool valid_cb = (card == adev->snd_card);
3169 pthread_mutex_unlock(&adev->lock);
3170
3171 if (!valid_cb)
3172 return;
3173
3174 lock_input_stream(in);
3175 if (in->card_status != status)
3176 in->card_status = status;
3177 pthread_mutex_unlock(&in->lock);
3178
3179 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3180 use_case_table[in->usecase],
3181 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3182
3183 // a better solution would be to report error back to AF and let
3184 // it put the stream to standby
3185 if (status == CARD_STATUS_OFFLINE)
3186 in_standby(&in->stream.common);
3187
3188 return;
3189}
3190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3192 size_t bytes)
3193{
3194 struct stream_in *in = (struct stream_in *)stream;
3195 struct audio_device *adev = in->dev;
3196 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003197 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003198 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199
Eric Laurenta1478072015-09-21 17:21:52 -07003200 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003201 const size_t frame_size = audio_stream_in_frame_size(stream);
3202 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003203
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003204 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003205 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003206 /* Read from sound trigger HAL */
3207 audio_extn_sound_trigger_read(in, buffer, bytes);
3208 pthread_mutex_unlock(&in->lock);
3209 return bytes;
3210 }
3211
Eric Laurent0e46adf2016-12-16 12:49:24 -08003212 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3213 ret = -ENOSYS;
3214 goto exit;
3215 }
3216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003218 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003220 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222 goto exit;
3223 }
3224 in->standby = 0;
3225 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226
Andy Hungd13f0d32017-06-12 13:58:37 -07003227 // errors that occur here are read errors.
3228 error_code = ERROR_CODE_READ;
3229
Haynes Mathew George03c40102016-01-29 17:57:48 -08003230 //what's the duration requested by the client?
3231 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3232 in->config.rate;
3233 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003234
Haynes Mathew George03c40102016-01-29 17:57:48 -08003235 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003237 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003238 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003239 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003240 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003241 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003242 if (ret < 0) {
3243 ALOGE("Failed to read w/err %s", strerror(errno));
3244 ret = -errno;
3245 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003246 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3247 if (bytes % 4 == 0) {
3248 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3249 int_buf_stream = buffer;
3250 for (size_t itt=0; itt < bytes/4 ; itt++) {
3251 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003252 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003253 } else {
3254 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3255 ret = -EINVAL;
3256 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003257 }
3258 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003259 }
3260
Haynes Mathew George03c40102016-01-29 17:57:48 -08003261 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263 /*
3264 * Instead of writing zeroes here, we could trust the hardware
3265 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003266 * 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 -08003267 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003268 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003270 in->frames_muted += frames;
3271 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272
3273exit:
3274 pthread_mutex_unlock(&in->lock);
3275
3276 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003277 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278 in_standby(&in->stream.common);
3279 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003280 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003281 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003282 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003283 }
3284 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003285 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003286 }
3287 return bytes;
3288}
3289
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003290static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291{
3292 return 0;
3293}
3294
Andy Hung6ebe5962016-01-15 17:46:57 -08003295static int in_get_capture_position(const struct audio_stream_in *stream,
3296 int64_t *frames, int64_t *time)
3297{
3298 if (stream == NULL || frames == NULL || time == NULL) {
3299 return -EINVAL;
3300 }
3301 struct stream_in *in = (struct stream_in *)stream;
3302 int ret = -ENOSYS;
3303
3304 lock_input_stream(in);
3305 if (in->pcm) {
3306 struct timespec timestamp;
3307 unsigned int avail;
3308 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3309 *frames = in->frames_read + avail;
3310 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3311 ret = 0;
3312 }
3313 }
3314 pthread_mutex_unlock(&in->lock);
3315 return ret;
3316}
3317
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003318static int add_remove_audio_effect(const struct audio_stream *stream,
3319 effect_handle_t effect,
3320 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003322 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003323 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003324 int status = 0;
3325 effect_descriptor_t desc;
3326
3327 status = (*effect)->get_descriptor(effect, &desc);
3328 if (status != 0)
3329 return status;
3330
Eric Laurenta1478072015-09-21 17:21:52 -07003331 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003332 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003333 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003334 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003335 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003336 in->enable_aec != enable &&
3337 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3338 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003339 if (!enable)
3340 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003341 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3342 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3343 adev->enable_voicerx = enable;
3344 struct audio_usecase *usecase;
3345 struct listnode *node;
3346 list_for_each(node, &adev->usecase_list) {
3347 usecase = node_to_item(node, struct audio_usecase, list);
3348 if (usecase->type == PCM_PLAYBACK) {
3349 select_devices(adev, usecase->id);
3350 break;
3351 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003352 }
3353 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003354 if (!in->standby)
3355 select_devices(in->dev, in->usecase);
3356 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003357 if (in->enable_ns != enable &&
3358 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3359 in->enable_ns = enable;
3360 if (!in->standby)
3361 select_devices(in->dev, in->usecase);
3362 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003363 pthread_mutex_unlock(&in->dev->lock);
3364 pthread_mutex_unlock(&in->lock);
3365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003366 return 0;
3367}
3368
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003369static int in_add_audio_effect(const struct audio_stream *stream,
3370 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371{
Eric Laurent994a6932013-07-17 11:51:42 -07003372 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003373 return add_remove_audio_effect(stream, effect, true);
3374}
3375
3376static int in_remove_audio_effect(const struct audio_stream *stream,
3377 effect_handle_t effect)
3378{
Eric Laurent994a6932013-07-17 11:51:42 -07003379 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003380 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003381}
3382
Eric Laurent0e46adf2016-12-16 12:49:24 -08003383static int in_stop(const struct audio_stream_in* stream)
3384{
3385 struct stream_in *in = (struct stream_in *)stream;
3386 struct audio_device *adev = in->dev;
3387
3388 int ret = -ENOSYS;
3389 ALOGV("%s", __func__);
3390 pthread_mutex_lock(&adev->lock);
3391 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3392 in->capture_started && in->pcm != NULL) {
3393 pcm_stop(in->pcm);
3394 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003395 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003396 }
3397 pthread_mutex_unlock(&adev->lock);
3398 return ret;
3399}
3400
3401static int in_start(const struct audio_stream_in* stream)
3402{
3403 struct stream_in *in = (struct stream_in *)stream;
3404 struct audio_device *adev = in->dev;
3405 int ret = -ENOSYS;
3406
3407 ALOGV("%s in %p", __func__, in);
3408 pthread_mutex_lock(&adev->lock);
3409 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3410 !in->capture_started && in->pcm != NULL) {
3411 if (!in->capture_started) {
3412 ret = start_input_stream(in);
3413 if (ret == 0) {
3414 in->capture_started = true;
3415 }
3416 }
3417 }
3418 pthread_mutex_unlock(&adev->lock);
3419 return ret;
3420}
3421
3422static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3423 int32_t min_size_frames,
3424 struct audio_mmap_buffer_info *info)
3425{
3426 struct stream_in *in = (struct stream_in *)stream;
3427 struct audio_device *adev = in->dev;
3428 int ret = 0;
3429 unsigned int offset1;
3430 unsigned int frames1;
3431 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003432 uint32_t mmap_size;
3433 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003434
3435 pthread_mutex_lock(&adev->lock);
3436 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003437
Eric Laurent0e46adf2016-12-16 12:49:24 -08003438 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003439 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003440 ret = -EINVAL;
3441 goto exit;
3442 }
3443 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003444 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003445 ALOGV("%s in %p", __func__, in);
3446 ret = -ENOSYS;
3447 goto exit;
3448 }
3449 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3450 if (in->pcm_device_id < 0) {
3451 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3452 __func__, in->pcm_device_id, in->usecase);
3453 ret = -EINVAL;
3454 goto exit;
3455 }
Phil Burkbc991042017-02-24 08:06:44 -08003456
3457 adjust_mmap_period_count(&in->config, min_size_frames);
3458
Eric Laurent0e46adf2016-12-16 12:49:24 -08003459 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3460 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3461 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3462 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3463 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3464 step = "open";
3465 ret = -ENODEV;
3466 goto exit;
3467 }
3468
3469 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3470 if (ret < 0) {
3471 step = "begin";
3472 goto exit;
3473 }
3474 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003475 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003476 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003477 ret = platform_get_mmap_data_fd(adev->platform,
3478 in->pcm_device_id, 1 /*capture*/,
3479 &info->shared_memory_fd,
3480 &mmap_size);
3481 if (ret < 0) {
3482 // Fall back to non exclusive mode
3483 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3484 } else {
3485 if (mmap_size < buffer_size) {
3486 step = "mmap";
3487 goto exit;
3488 }
3489 // FIXME: indicate exclusive mode support by returning a negative buffer size
3490 info->buffer_size_frames *= -1;
3491 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003492
Haynes Mathew George96483a22017-03-28 14:52:47 -07003493 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003494
3495 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3496 if (ret < 0) {
3497 step = "commit";
3498 goto exit;
3499 }
3500
Phil Burkbc991042017-02-24 08:06:44 -08003501 in->standby = false;
3502 ret = 0;
3503
Eric Laurent0e46adf2016-12-16 12:49:24 -08003504 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3505 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003506
3507exit:
3508 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003509 if (in->pcm == NULL) {
3510 ALOGE("%s: %s - %d", __func__, step, ret);
3511 } else {
3512 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003513 pcm_close(in->pcm);
3514 in->pcm = NULL;
3515 }
3516 }
3517 pthread_mutex_unlock(&adev->lock);
3518 return ret;
3519}
3520
3521static int in_get_mmap_position(const struct audio_stream_in *stream,
3522 struct audio_mmap_position *position)
3523{
3524 struct stream_in *in = (struct stream_in *)stream;
3525 ALOGVV("%s", __func__);
3526 if (position == NULL) {
3527 return -EINVAL;
3528 }
3529 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3530 return -ENOSYS;
3531 }
3532 if (in->pcm == NULL) {
3533 return -ENOSYS;
3534 }
3535 struct timespec ts = { 0, 0 };
3536 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3537 if (ret < 0) {
3538 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3539 return ret;
3540 }
Andy Hungfc044e12017-03-20 09:24:22 -07003541 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003542 return 0;
3543}
3544
3545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546static int adev_open_output_stream(struct audio_hw_device *dev,
3547 audio_io_handle_t handle,
3548 audio_devices_t devices,
3549 audio_output_flags_t flags,
3550 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003551 struct audio_stream_out **stream_out,
3552 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003553{
3554 struct audio_device *adev = (struct audio_device *)dev;
3555 struct stream_out *out;
3556 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003557 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3558 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3559 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3560 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561
Eric Laurent994a6932013-07-17 11:51:42 -07003562 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 __func__, config->sample_rate, config->channel_mask, devices, flags);
3564 *stream_out = NULL;
3565 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3566
3567 if (devices == AUDIO_DEVICE_NONE)
3568 devices = AUDIO_DEVICE_OUT_SPEAKER;
3569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570 out->flags = flags;
3571 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003572 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003573 out->format = config->format;
3574 out->sample_rate = config->sample_rate;
3575 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3576 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003577 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578
3579 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003580 if (audio_is_linear_pcm(out->format) &&
3581 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003582 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003583 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003584 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003585 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003586 if (config->sample_rate == 0)
3587 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3588 if (config->channel_mask == 0)
3589 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3590 if (config->format == AUDIO_FORMAT_DEFAULT)
3591 config->format = AUDIO_FORMAT_PCM_16_BIT;
3592 } else if (is_usb_dev) {
3593 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3594 &config->format,
3595 &out->supported_formats[0],
3596 MAX_SUPPORTED_FORMATS,
3597 &config->channel_mask,
3598 &out->supported_channel_masks[0],
3599 MAX_SUPPORTED_CHANNEL_MASKS,
3600 &config->sample_rate,
3601 &out->supported_sample_rates[0],
3602 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003603 ALOGV("plugged dev USB ret %d", ret);
3604 } else {
3605 ret = -1;
3606 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003607 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003608 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003609 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003610
Haynes Mathew George569b7482017-05-08 14:44:27 -07003611 out->channel_mask = config->channel_mask;
3612 out->sample_rate = config->sample_rate;
3613 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003614 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3615 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003616 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003617 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003618 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003619 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3620 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003621 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003622 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003623 pthread_mutex_lock(&adev->lock);
3624 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3625 pthread_mutex_unlock(&adev->lock);
3626
3627 // reject offload during card offline to allow
3628 // fallback to s/w paths
3629 if (offline) {
3630 ret = -ENODEV;
3631 goto error_open;
3632 }
3633
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003634 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3635 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3636 ALOGE("%s: Unsupported Offload information", __func__);
3637 ret = -EINVAL;
3638 goto error_open;
3639 }
3640 if (!is_supported_format(config->offload_info.format)) {
3641 ALOGE("%s: Unsupported audio format", __func__);
3642 ret = -EINVAL;
3643 goto error_open;
3644 }
3645
3646 out->compr_config.codec = (struct snd_codec *)
3647 calloc(1, sizeof(struct snd_codec));
3648
3649 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3650 if (config->offload_info.channel_mask)
3651 out->channel_mask = config->offload_info.channel_mask;
3652 else if (config->channel_mask)
3653 out->channel_mask = config->channel_mask;
3654 out->format = config->offload_info.format;
3655 out->sample_rate = config->offload_info.sample_rate;
3656
3657 out->stream.set_callback = out_set_callback;
3658 out->stream.pause = out_pause;
3659 out->stream.resume = out_resume;
3660 out->stream.drain = out_drain;
3661 out->stream.flush = out_flush;
3662
3663 out->compr_config.codec->id =
3664 get_snd_codec_id(config->offload_info.format);
3665 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3666 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003667 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003668 out->compr_config.codec->bit_rate =
3669 config->offload_info.bit_rate;
3670 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003671 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003672 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3673
3674 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3675 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003676
3677 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003678 create_offload_callback_thread(out);
3679 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3680 __func__, config->offload_info.version,
3681 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003682 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003683 switch (config->sample_rate) {
3684 case 8000:
3685 case 16000:
3686 case 48000:
3687 out->sample_rate = config->sample_rate;
3688 break;
3689 default:
3690 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003691 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003692 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003693 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3694 out->config = pcm_config_afe_proxy_playback;
3695 adev->voice_tx_output = out;
vivek mehtaa68fea62017-06-08 19:04:02 -07003696 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3697 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3698 AUDIO_OUTPUT_FLAG_VOIP_RX))) {
3699 uint32_t buffer_size, frame_size;
3700 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3701 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3702 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3703 out->config = pcm_config_voip;
3704 out->config.format = pcm_format_from_audio_format(config->format);
3705 out->config.rate = config->sample_rate;
3706 out->config.channels =
3707 audio_channel_count_from_out_mask(config->channel_mask);
3708 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3709 config->sample_rate,
3710 config->format,
3711 out->config.channels,
3712 false /*is_low_latency*/);
3713 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3714 out->config.period_size = buffer_size / frame_size;
3715 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3716 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003718 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3719 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3720 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003721 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3722 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3723 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003724 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3725 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003726 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003727 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003728 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3729 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3730 out->config = pcm_config_mmap_playback;
3731 out->stream.start = out_start;
3732 out->stream.stop = out_stop;
3733 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3734 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003735 } else {
3736 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3737 out->config = pcm_config_low_latency;
3738 }
3739 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003740 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003741 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003742 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003744
3745 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3746 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3747 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3748 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3749 __func__, config->sample_rate, config->format, config->channel_mask);
3750 config->sample_rate = out->sample_rate;
3751 config->format = out->format;
3752 config->channel_mask = out->channel_mask;
3753 ret = -EINVAL;
3754 goto error_open;
3755 }
3756
Andy Hung6fcba9c2014-03-18 11:53:32 -07003757 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3758 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003759
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003760 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003761 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003762 adev->primary_output = out;
3763 else {
3764 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003765 ret = -EEXIST;
3766 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003767 }
3768 }
3769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 /* Check if this usecase is already existing */
3771 pthread_mutex_lock(&adev->lock);
3772 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3773 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003775 ret = -EEXIST;
3776 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777 }
3778 pthread_mutex_unlock(&adev->lock);
3779
3780 out->stream.common.get_sample_rate = out_get_sample_rate;
3781 out->stream.common.set_sample_rate = out_set_sample_rate;
3782 out->stream.common.get_buffer_size = out_get_buffer_size;
3783 out->stream.common.get_channels = out_get_channels;
3784 out->stream.common.get_format = out_get_format;
3785 out->stream.common.set_format = out_set_format;
3786 out->stream.common.standby = out_standby;
3787 out->stream.common.dump = out_dump;
3788 out->stream.common.set_parameters = out_set_parameters;
3789 out->stream.common.get_parameters = out_get_parameters;
3790 out->stream.common.add_audio_effect = out_add_audio_effect;
3791 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3792 out->stream.get_latency = out_get_latency;
3793 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003794#ifdef NO_AUDIO_OUT
3795 out->stream.write = out_write_for_no_output;
3796#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003798#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799 out->stream.get_render_position = out_get_render_position;
3800 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003801 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802
Eric Laurent0e46adf2016-12-16 12:49:24 -08003803 if (out->realtime)
3804 out->af_period_multiplier = af_period_multiplier;
3805 else
3806 out->af_period_multiplier = 1;
3807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003809 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003810 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003812 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003813 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3815
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 config->format = out->stream.common.get_format(&out->stream.common);
3817 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3818 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3819
Andy Hunga452b0a2017-03-15 14:51:15 -07003820 out->error_log = error_log_create(
3821 ERROR_LOG_ENTRIES,
3822 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3823
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003824 /*
3825 By locking output stream before registering, we allow the callback
3826 to update stream's state only after stream's initial state is set to
3827 adev state.
3828 */
3829 lock_output_stream(out);
3830 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3831 pthread_mutex_lock(&adev->lock);
3832 out->card_status = adev->card_status;
3833 pthread_mutex_unlock(&adev->lock);
3834 pthread_mutex_unlock(&out->lock);
3835
vivek mehta4a824772017-06-08 19:05:49 -07003836 stream_app_type_cfg_init(&out->app_type_cfg);
3837
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003839
Eric Laurent994a6932013-07-17 11:51:42 -07003840 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003842
3843error_open:
3844 free(out);
3845 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003846 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003847 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848}
3849
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003850static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851 struct audio_stream_out *stream)
3852{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003853 struct stream_out *out = (struct stream_out *)stream;
3854 struct audio_device *adev = out->dev;
3855
Eric Laurent994a6932013-07-17 11:51:42 -07003856 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003857
3858 // must deregister from sndmonitor first to prevent races
3859 // between the callback and close_stream
3860 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003862 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3863 destroy_offload_callback_thread(out);
3864
3865 if (out->compr_config.codec != NULL)
3866 free(out->compr_config.codec);
3867 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003868
3869 if (adev->voice_tx_output == out)
3870 adev->voice_tx_output = NULL;
3871
Andy Hunga452b0a2017-03-15 14:51:15 -07003872 error_log_destroy(out->error_log);
3873 out->error_log = NULL;
3874
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003875 pthread_cond_destroy(&out->cond);
3876 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003877 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003878 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879}
3880
3881static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3882{
3883 struct audio_device *adev = (struct audio_device *)dev;
3884 struct str_parms *parms;
3885 char *str;
3886 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003887 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003889 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003890
Joe Onorato188b6222016-03-01 11:02:27 -08003891 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003892
3893 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894
3895 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003896 status = voice_set_parameters(adev, parms);
3897 if (status != 0) {
3898 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899 }
3900
3901 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3902 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003903 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3905 adev->bluetooth_nrec = true;
3906 else
3907 adev->bluetooth_nrec = false;
3908 }
3909
3910 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3911 if (ret >= 0) {
3912 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3913 adev->screen_off = false;
3914 else
3915 adev->screen_off = true;
3916 }
3917
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003918 ret = str_parms_get_int(parms, "rotation", &val);
3919 if (ret >= 0) {
3920 bool reverse_speakers = false;
3921 switch(val) {
3922 // FIXME: note that the code below assumes that the speakers are in the correct placement
3923 // relative to the user when the device is rotated 90deg from its default rotation. This
3924 // assumption is device-specific, not platform-specific like this code.
3925 case 270:
3926 reverse_speakers = true;
3927 break;
3928 case 0:
3929 case 90:
3930 case 180:
3931 break;
3932 default:
3933 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003934 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003935 }
Eric Laurent03f09432014-03-25 18:09:11 -07003936 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07003937 // check and set swap
3938 // - check if orientation changed and speaker active
3939 // - set rotation and cache the rotation value
3940 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003941 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003942 }
3943
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003944 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3945 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003946 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003947 }
3948
David Linee3fe402017-03-13 10:00:42 -07003949 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3950 if (ret >= 0) {
3951 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003952 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003953 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3954 if (ret >= 0) {
3955 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003956 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003957 }
Eric Laurent99dab492017-06-17 15:19:08 -07003958 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003959 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3960 if (ret >= 0) {
3961 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003962 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003963 }
3964 }
3965 }
3966
3967 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3968 if (ret >= 0) {
3969 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003970 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003971 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3972 if (ret >= 0) {
3973 const int card = atoi(value);
3974
Eric Laurent99dab492017-06-17 15:19:08 -07003975 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003976 }
Eric Laurent99dab492017-06-17 15:19:08 -07003977 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003978 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3979 if (ret >= 0) {
3980 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003981 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003982 }
3983 }
3984 }
3985
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003986 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003987done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003988 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003989 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003990 ALOGV("%s: exit with code(%d)", __func__, status);
3991 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992}
3993
3994static char* adev_get_parameters(const struct audio_hw_device *dev,
3995 const char *keys)
3996{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003997 struct audio_device *adev = (struct audio_device *)dev;
3998 struct str_parms *reply = str_parms_create();
3999 struct str_parms *query = str_parms_create_str(keys);
4000 char *str;
4001
4002 pthread_mutex_lock(&adev->lock);
4003
4004 voice_get_parameters(adev, query, reply);
4005 str = str_parms_to_str(reply);
4006 str_parms_destroy(query);
4007 str_parms_destroy(reply);
4008
4009 pthread_mutex_unlock(&adev->lock);
4010 ALOGV("%s: exit: returns - %s", __func__, str);
4011 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012}
4013
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004014static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004015{
4016 return 0;
4017}
4018
Haynes Mathew George5191a852013-09-11 14:19:36 -07004019static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4020{
4021 int ret;
4022 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004023
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004024 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4025
Haynes Mathew George5191a852013-09-11 14:19:36 -07004026 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004027 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004028 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004029
Haynes Mathew George5191a852013-09-11 14:19:36 -07004030 return ret;
4031}
4032
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004033static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004034{
4035 return -ENOSYS;
4036}
4037
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004038static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4039 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040{
4041 return -ENOSYS;
4042}
4043
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004044static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __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_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050{
4051 return -ENOSYS;
4052}
4053
4054static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4055{
4056 struct audio_device *adev = (struct audio_device *)dev;
4057
4058 pthread_mutex_lock(&adev->lock);
4059 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004060 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004062 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4063 voice_is_in_call(adev)) {
4064 voice_stop_call(adev);
4065 adev->current_call_output = NULL;
4066 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067 }
4068 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004069
4070 audio_extn_extspk_set_mode(adev->extspk, mode);
4071
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004072 return 0;
4073}
4074
4075static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4076{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004077 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004078 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004079
Eric Laurent2bafff12016-03-17 12:17:23 -07004080 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004081 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004082 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4083 ret = audio_extn_hfp_set_mic_mute(adev, state);
4084 } else {
4085 ret = voice_set_mic_mute(adev, state);
4086 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004087 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004088 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004089
4090 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004091}
4092
4093static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4094{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004095 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004096 return 0;
4097}
4098
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004099static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100 const struct audio_config *config)
4101{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004102 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103
Eric Laurent74b55762017-07-09 17:04:53 -07004104 /* Don't know if USB HIFI in this context so use true to be conservative */
4105 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4106 true /*is_usb_hifi */) != 0)
4107 return 0;
4108
vivek mehtaa68fea62017-06-08 19:04:02 -07004109 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4110 config->sample_rate, config->format,
4111 channel_count,
4112 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113}
4114
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004115static bool adev_input_allow_hifi_record(struct audio_device *adev,
4116 audio_devices_t devices,
4117 audio_input_flags_t flags,
4118 audio_source_t source) {
4119 const bool allowed = true;
4120
4121 if (!audio_is_usb_in_device(devices))
4122 return !allowed;
4123
4124 switch (flags) {
4125 case AUDIO_INPUT_FLAG_NONE:
4126 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4127 break;
4128 default:
4129 return !allowed;
4130 }
4131
4132 switch (source) {
4133 case AUDIO_SOURCE_DEFAULT:
4134 case AUDIO_SOURCE_MIC:
4135 case AUDIO_SOURCE_UNPROCESSED:
4136 break;
4137 default:
4138 return !allowed;
4139 }
4140
4141 switch (adev->mode) {
4142 case 0:
4143 break;
4144 default:
4145 return !allowed;
4146 }
4147
4148 return allowed;
4149}
4150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004152 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004153 audio_devices_t devices,
4154 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004155 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004156 audio_input_flags_t flags,
4157 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004158 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159{
4160 struct audio_device *adev = (struct audio_device *)dev;
4161 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004162 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004163 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004164 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004165 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004166 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4167 devices,
4168 flags,
4169 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004170 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004171 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004172
Eric Laurent74b55762017-07-09 17:04:53 -07004173 if (!(is_usb_dev && may_use_hifi_record)) {
4174 if (config->sample_rate == 0)
4175 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4176 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4177 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4178 if (config->format == AUDIO_FORMAT_DEFAULT)
4179 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004180
Eric Laurent74b55762017-07-09 17:04:53 -07004181 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4182
4183 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4184 return -EINVAL;
4185 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004186
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004187 if (audio_extn_tfa_98xx_is_supported() &&
4188 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004189 return -EINVAL;
4190
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4192
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004193 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004194 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196 in->stream.common.get_sample_rate = in_get_sample_rate;
4197 in->stream.common.set_sample_rate = in_set_sample_rate;
4198 in->stream.common.get_buffer_size = in_get_buffer_size;
4199 in->stream.common.get_channels = in_get_channels;
4200 in->stream.common.get_format = in_get_format;
4201 in->stream.common.set_format = in_set_format;
4202 in->stream.common.standby = in_standby;
4203 in->stream.common.dump = in_dump;
4204 in->stream.common.set_parameters = in_set_parameters;
4205 in->stream.common.get_parameters = in_get_parameters;
4206 in->stream.common.add_audio_effect = in_add_audio_effect;
4207 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4208 in->stream.set_gain = in_set_gain;
4209 in->stream.read = in_read;
4210 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004211 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212
4213 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004214 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004216 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004217 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004218 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219
Haynes Mathew George569b7482017-05-08 14:44:27 -07004220 if (is_usb_dev && may_use_hifi_record) {
4221 /* HiFi record selects an appropriate format, channel, rate combo
4222 depending on sink capabilities*/
4223 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4224 &config->format,
4225 &in->supported_formats[0],
4226 MAX_SUPPORTED_FORMATS,
4227 &config->channel_mask,
4228 &in->supported_channel_masks[0],
4229 MAX_SUPPORTED_CHANNEL_MASKS,
4230 &config->sample_rate,
4231 &in->supported_sample_rates[0],
4232 MAX_SUPPORTED_SAMPLE_RATES);
4233 if (ret != 0) {
4234 ret = -EINVAL;
4235 goto err_open;
4236 }
Eric Laurent74b55762017-07-09 17:04:53 -07004237 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004238 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004239 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004240 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4241 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4242 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4243 bool ret_error = false;
4244 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4245 from HAL is 8_24
4246 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4247 8_24 return error indicating supported format is 8_24
4248 *> In case of any other source requesting 24 bit or float return error
4249 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004250
vivek mehta57ff9b52016-04-28 14:13:08 -07004251 on error flinger will retry with supported format passed
4252 */
4253 if (source != AUDIO_SOURCE_UNPROCESSED) {
4254 config->format = AUDIO_FORMAT_PCM_16_BIT;
4255 ret_error = true;
4256 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4257 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4258 ret_error = true;
4259 }
4260
4261 if (ret_error) {
4262 ret = -EINVAL;
4263 goto err_open;
4264 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004265 }
4266
vivek mehta57ff9b52016-04-28 14:13:08 -07004267 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004268 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004269
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004270 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004271 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4272 if (config->sample_rate == 0)
4273 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4274 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4275 config->sample_rate != 8000) {
4276 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4277 ret = -EINVAL;
4278 goto err_open;
4279 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004280
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004281 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4282 config->format = AUDIO_FORMAT_PCM_16_BIT;
4283 ret = -EINVAL;
4284 goto err_open;
4285 }
4286
4287 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4288 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004289 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004290 } else if (is_usb_dev && may_use_hifi_record) {
4291 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4292 in->config = pcm_config_audio_capture;
4293 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004294 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4295 config->sample_rate,
4296 config->format,
4297 channel_count,
4298 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004299 in->config.period_size = buffer_size / frame_size;
4300 in->config.rate = config->sample_rate;
4301 in->af_period_multiplier = 1;
4302 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004303 } else {
4304 in->usecase = USECASE_AUDIO_RECORD;
4305 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004306 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004307 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004308#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004309 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004310#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004311 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004312 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004313 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004314 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004315 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4316 config->sample_rate,
4317 config->format,
4318 channel_count,
4319 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004320 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004321 in->config.rate = config->sample_rate;
4322 in->af_period_multiplier = 1;
4323 } else {
4324 // period size is left untouched for rt mode playback
4325 in->config = pcm_config_audio_capture_rt;
4326 in->af_period_multiplier = af_period_multiplier;
4327 }
4328 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4329 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004330 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004331 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4332 in->config = pcm_config_mmap_capture;
4333 in->stream.start = in_start;
4334 in->stream.stop = in_stop;
4335 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4336 in->stream.get_mmap_position = in_get_mmap_position;
4337 in->af_period_multiplier = 1;
4338 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004339 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
4340 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004341 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004342 (config->sample_rate == 8000 ||
4343 config->sample_rate == 16000 ||
4344 config->sample_rate == 32000 ||
4345 config->sample_rate == 48000) &&
4346 channel_count == 1) {
4347 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4348 in->config = pcm_config_audio_capture;
4349 frame_size = audio_stream_in_frame_size(&in->stream);
4350 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4351 config->sample_rate,
4352 config->format,
4353 channel_count, false /*is_low_latency*/);
4354 in->config.period_size = buffer_size / frame_size;
4355 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4356 in->config.rate = config->sample_rate;
4357 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004358 } else {
4359 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004360 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004361 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4362 config->sample_rate,
4363 config->format,
4364 channel_count,
4365 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004366 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004367 in->config.rate = config->sample_rate;
4368 in->af_period_multiplier = 1;
4369 }
4370 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4371 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004372 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004374 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004375 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004376
Andy Hungd13f0d32017-06-12 13:58:37 -07004377 in->error_log = error_log_create(
4378 ERROR_LOG_ENTRIES,
4379 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4380
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004381 /* This stream could be for sound trigger lab,
4382 get sound trigger pcm if present */
4383 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004385 lock_input_stream(in);
4386 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4387 pthread_mutex_lock(&adev->lock);
4388 in->card_status = adev->card_status;
4389 pthread_mutex_unlock(&adev->lock);
4390 pthread_mutex_unlock(&in->lock);
4391
vivek mehta4a824772017-06-08 19:05:49 -07004392 stream_app_type_cfg_init(&in->app_type_cfg);
4393
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004394 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004395 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004396 return 0;
4397
4398err_open:
4399 free(in);
4400 *stream_in = NULL;
4401 return ret;
4402}
4403
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004404static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405 struct audio_stream_in *stream)
4406{
Andy Hungd13f0d32017-06-12 13:58:37 -07004407 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004408 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004409
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004410 // must deregister from sndmonitor first to prevent races
4411 // between the callback and close_stream
4412 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004414
4415 error_log_destroy(in->error_log);
4416 in->error_log = NULL;
4417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418 free(stream);
4419
4420 return;
4421}
4422
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004423static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004424{
4425 return 0;
4426}
4427
Andy Hung31aca912014-03-20 17:14:59 -07004428/* verifies input and output devices and their capabilities.
4429 *
4430 * This verification is required when enabling extended bit-depth or
4431 * sampling rates, as not all qcom products support it.
4432 *
4433 * Suitable for calling only on initialization such as adev_open().
4434 * It fills the audio_device use_case_table[] array.
4435 *
4436 * Has a side-effect that it needs to configure audio routing / devices
4437 * in order to power up the devices and read the device parameters.
4438 * It does not acquire any hw device lock. Should restore the devices
4439 * back to "normal state" upon completion.
4440 */
4441static int adev_verify_devices(struct audio_device *adev)
4442{
4443 /* enumeration is a bit difficult because one really wants to pull
4444 * the use_case, device id, etc from the hidden pcm_device_table[].
4445 * In this case there are the following use cases and device ids.
4446 *
4447 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4448 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004449 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004450 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4451 * [USECASE_AUDIO_RECORD] = {0, 0},
4452 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4453 * [USECASE_VOICE_CALL] = {2, 2},
4454 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004455 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004456 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4457 */
4458
4459 /* should be the usecases enabled in adev_open_input_stream() */
4460 static const int test_in_usecases[] = {
4461 USECASE_AUDIO_RECORD,
4462 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4463 };
4464 /* should be the usecases enabled in adev_open_output_stream()*/
4465 static const int test_out_usecases[] = {
4466 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4467 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4468 };
4469 static const usecase_type_t usecase_type_by_dir[] = {
4470 PCM_PLAYBACK,
4471 PCM_CAPTURE,
4472 };
4473 static const unsigned flags_by_dir[] = {
4474 PCM_OUT,
4475 PCM_IN,
4476 };
4477
4478 size_t i;
4479 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004480 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004481 char info[512]; /* for possible debug info */
4482
4483 for (dir = 0; dir < 2; ++dir) {
4484 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4485 const unsigned flags_dir = flags_by_dir[dir];
4486 const size_t testsize =
4487 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4488 const int *testcases =
4489 dir ? test_in_usecases : test_out_usecases;
4490 const audio_devices_t audio_device =
4491 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4492
4493 for (i = 0; i < testsize; ++i) {
4494 const audio_usecase_t audio_usecase = testcases[i];
4495 int device_id;
4496 snd_device_t snd_device;
4497 struct pcm_params **pparams;
4498 struct stream_out out;
4499 struct stream_in in;
4500 struct audio_usecase uc_info;
4501 int retval;
4502
4503 pparams = &adev->use_case_table[audio_usecase];
4504 pcm_params_free(*pparams); /* can accept null input */
4505 *pparams = NULL;
4506
4507 /* find the device ID for the use case (signed, for error) */
4508 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4509 if (device_id < 0)
4510 continue;
4511
4512 /* prepare structures for device probing */
4513 memset(&uc_info, 0, sizeof(uc_info));
4514 uc_info.id = audio_usecase;
4515 uc_info.type = usecase_type;
4516 if (dir) {
4517 adev->active_input = &in;
4518 memset(&in, 0, sizeof(in));
4519 in.device = audio_device;
4520 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4521 uc_info.stream.in = &in;
4522 } else {
4523 adev->active_input = NULL;
4524 }
4525 memset(&out, 0, sizeof(out));
4526 out.devices = audio_device; /* only field needed in select_devices */
4527 uc_info.stream.out = &out;
4528 uc_info.devices = audio_device;
4529 uc_info.in_snd_device = SND_DEVICE_NONE;
4530 uc_info.out_snd_device = SND_DEVICE_NONE;
4531 list_add_tail(&adev->usecase_list, &uc_info.list);
4532
4533 /* select device - similar to start_(in/out)put_stream() */
4534 retval = select_devices(adev, audio_usecase);
4535 if (retval >= 0) {
4536 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4537#if LOG_NDEBUG == 0
4538 if (*pparams) {
4539 ALOGV("%s: (%s) card %d device %d", __func__,
4540 dir ? "input" : "output", card_id, device_id);
4541 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004542 } else {
4543 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4544 }
4545#endif
4546 }
4547
4548 /* deselect device - similar to stop_(in/out)put_stream() */
4549 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004550 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004551 /* 2. Disable the rx device */
4552 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004553 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004554 list_remove(&uc_info.list);
4555 }
4556 }
4557 adev->active_input = NULL; /* restore adev state */
4558 return 0;
4559}
4560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561static int adev_close(hw_device_t *device)
4562{
Andy Hung31aca912014-03-20 17:14:59 -07004563 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004565
4566 if (!adev)
4567 return 0;
4568
4569 pthread_mutex_lock(&adev_init_lock);
4570
4571 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004572 audio_extn_snd_mon_unregister_listener(adev);
4573 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004574 audio_route_free(adev->audio_route);
4575 free(adev->snd_dev_ref_cnt);
4576 platform_deinit(adev->platform);
4577 audio_extn_extspk_deinit(adev->extspk);
4578 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004579 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004580 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4581 pcm_params_free(adev->use_case_table[i]);
4582 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004583 if (adev->adm_deinit)
4584 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004585 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004586 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004587
4588 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004590 return 0;
4591}
4592
Glenn Kasten4f993392014-05-14 07:30:48 -07004593/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4594 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4595 * just that it _might_ work.
4596 */
4597static int period_size_is_plausible_for_low_latency(int period_size)
4598{
4599 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004600 case 48:
4601 case 96:
4602 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004603 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004604 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004605 case 240:
4606 case 320:
4607 case 480:
4608 return 1;
4609 default:
4610 return 0;
4611 }
4612}
4613
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004614static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4615{
4616 int card;
4617 card_status_t status;
4618
4619 if (!parms)
4620 return;
4621
4622 if (parse_snd_card_status(parms, &card, &status) < 0)
4623 return;
4624
4625 pthread_mutex_lock(&adev->lock);
4626 bool valid_cb = (card == adev->snd_card);
4627 if (valid_cb) {
4628 if (adev->card_status != status) {
4629 adev->card_status = status;
4630 platform_snd_card_update(adev->platform, status);
4631 }
4632 }
4633 pthread_mutex_unlock(&adev->lock);
4634 return;
4635}
4636
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004637static int adev_open(const hw_module_t *module, const char *name,
4638 hw_device_t **device)
4639{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004640 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641
Eric Laurent2bafff12016-03-17 12:17:23 -07004642 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004643 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004644 pthread_mutex_lock(&adev_init_lock);
4645 if (audio_device_ref_count != 0) {
4646 *device = &adev->device.common;
4647 audio_device_ref_count++;
4648 ALOGV("%s: returning existing instance of adev", __func__);
4649 ALOGV("%s: exit", __func__);
4650 pthread_mutex_unlock(&adev_init_lock);
4651 return 0;
4652 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004653 adev = calloc(1, sizeof(struct audio_device));
4654
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004655 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4658 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4659 adev->device.common.module = (struct hw_module_t *)module;
4660 adev->device.common.close = adev_close;
4661
4662 adev->device.init_check = adev_init_check;
4663 adev->device.set_voice_volume = adev_set_voice_volume;
4664 adev->device.set_master_volume = adev_set_master_volume;
4665 adev->device.get_master_volume = adev_get_master_volume;
4666 adev->device.set_master_mute = adev_set_master_mute;
4667 adev->device.get_master_mute = adev_get_master_mute;
4668 adev->device.set_mode = adev_set_mode;
4669 adev->device.set_mic_mute = adev_set_mic_mute;
4670 adev->device.get_mic_mute = adev_get_mic_mute;
4671 adev->device.set_parameters = adev_set_parameters;
4672 adev->device.get_parameters = adev_get_parameters;
4673 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4674 adev->device.open_output_stream = adev_open_output_stream;
4675 adev->device.close_output_stream = adev_close_output_stream;
4676 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004677
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004678 adev->device.close_input_stream = adev_close_input_stream;
4679 adev->device.dump = adev_dump;
4680
4681 /* Set the default route before the PCM stream is opened */
4682 pthread_mutex_lock(&adev->lock);
4683 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004684 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004685 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004686 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004687 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004688 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004689 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004690 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004691 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004692 pthread_mutex_unlock(&adev->lock);
4693
4694 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004695 adev->platform = platform_init(adev);
4696 if (!adev->platform) {
4697 free(adev->snd_dev_ref_cnt);
4698 free(adev);
4699 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4700 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004701 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004702 return -EINVAL;
4703 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004704 adev->extspk = audio_extn_extspk_init(adev);
4705
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004706 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4707 if (adev->visualizer_lib == NULL) {
4708 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4709 } else {
4710 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4711 adev->visualizer_start_output =
4712 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4713 "visualizer_hal_start_output");
4714 adev->visualizer_stop_output =
4715 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4716 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004717 }
4718
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004719 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4720 if (adev->offload_effects_lib == NULL) {
4721 ALOGW("%s: DLOPEN failed for %s", __func__,
4722 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4723 } else {
4724 ALOGV("%s: DLOPEN successful for %s", __func__,
4725 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4726 adev->offload_effects_start_output =
4727 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4728 "offload_effects_bundle_hal_start_output");
4729 adev->offload_effects_stop_output =
4730 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4731 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004732 }
4733
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004734 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4735 if (adev->adm_lib == NULL) {
4736 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4737 } else {
4738 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4739 adev->adm_init = (adm_init_t)
4740 dlsym(adev->adm_lib, "adm_init");
4741 adev->adm_deinit = (adm_deinit_t)
4742 dlsym(adev->adm_lib, "adm_deinit");
4743 adev->adm_register_input_stream = (adm_register_input_stream_t)
4744 dlsym(adev->adm_lib, "adm_register_input_stream");
4745 adev->adm_register_output_stream = (adm_register_output_stream_t)
4746 dlsym(adev->adm_lib, "adm_register_output_stream");
4747 adev->adm_deregister_stream = (adm_deregister_stream_t)
4748 dlsym(adev->adm_lib, "adm_deregister_stream");
4749 adev->adm_request_focus = (adm_request_focus_t)
4750 dlsym(adev->adm_lib, "adm_request_focus");
4751 adev->adm_abandon_focus = (adm_abandon_focus_t)
4752 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004753 adev->adm_set_config = (adm_set_config_t)
4754 dlsym(adev->adm_lib, "adm_set_config");
4755 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4756 dlsym(adev->adm_lib, "adm_request_focus_v2");
4757 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4758 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4759 adev->adm_on_routing_change = (adm_on_routing_change_t)
4760 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004761 }
4762
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004763 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004764 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004766 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004767
Andy Hung31aca912014-03-20 17:14:59 -07004768 if (k_enable_extended_precision)
4769 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004770
Glenn Kasten4f993392014-05-14 07:30:48 -07004771 char value[PROPERTY_VALUE_MAX];
4772 int trial;
4773 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4774 trial = atoi(value);
4775 if (period_size_is_plausible_for_low_latency(trial)) {
4776 pcm_config_low_latency.period_size = trial;
4777 pcm_config_low_latency.start_threshold = trial / 4;
4778 pcm_config_low_latency.avail_min = trial / 4;
4779 configured_low_latency_capture_period_size = trial;
4780 }
4781 }
4782 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4783 trial = atoi(value);
4784 if (period_size_is_plausible_for_low_latency(trial)) {
4785 configured_low_latency_capture_period_size = trial;
4786 }
4787 }
4788
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004789 // commented as full set of app type cfg is sent from platform
4790 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004791 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004792
4793 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4794 af_period_multiplier = atoi(value);
4795 if (af_period_multiplier < 0) {
4796 af_period_multiplier = 2;
4797 } else if (af_period_multiplier > 4) {
4798 af_period_multiplier = 4;
4799 }
4800 ALOGV("new period_multiplier = %d", af_period_multiplier);
4801 }
4802
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004803 audio_extn_tfa_98xx_init(adev);
4804
vivek mehta1a9b7c02015-06-25 11:49:38 -07004805 pthread_mutex_unlock(&adev_init_lock);
4806
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004807 if (adev->adm_init)
4808 adev->adm_data = adev->adm_init();
4809
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004810 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004811 audio_extn_snd_mon_init();
4812 pthread_mutex_lock(&adev->lock);
4813 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4814 adev->card_status = CARD_STATUS_ONLINE;
4815 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004816 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004817
Eric Laurent2bafff12016-03-17 12:17:23 -07004818 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004819 return 0;
4820}
4821
4822static struct hw_module_methods_t hal_module_methods = {
4823 .open = adev_open,
4824};
4825
4826struct audio_module HAL_MODULE_INFO_SYM = {
4827 .common = {
4828 .tag = HARDWARE_MODULE_TAG,
4829 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4830 .hal_api_version = HARDWARE_HAL_API_VERSION,
4831 .id = AUDIO_HARDWARE_MODULE_ID,
4832 .name = "QCOM Audio HAL",
4833 .author = "Code Aurora Forum",
4834 .methods = &hal_module_methods,
4835 },
4836};