blob: c8771869014d2360ef814046ff83a8e7dd212b04 [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 &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700861 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
862 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700863 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
865 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700866 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700867 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700868 switch_device[usecase->id] = true;
869 num_uc_to_switch++;
870 }
871 }
872
873 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 list_for_each(node, &adev->usecase_list) {
875 usecase = node_to_item(node, struct audio_usecase, list);
876 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700877 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900878 }
879 }
880
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700881 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900882 list_for_each(node, &adev->usecase_list) {
883 usecase = node_to_item(node, struct audio_usecase, list);
884 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700885 d_device = derive_playback_snd_device(usecase, uc_info,
886 snd_device);
887 enable_snd_device(adev, d_device);
888 /* Update the out_snd_device before enabling the audio route */
889 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 }
891 }
892
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 /* Re-route all the usecases on the shared backend other than the
894 specified usecase to new snd devices */
895 list_for_each(node, &adev->usecase_list) {
896 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700898 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 }
900 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700901 }
902}
903
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700904static void check_and_route_capture_usecases(struct audio_device *adev,
905 struct audio_usecase *uc_info,
906 snd_device_t snd_device)
907{
908 struct listnode *node;
909 struct audio_usecase *usecase;
910 bool switch_device[AUDIO_USECASE_MAX];
911 int i, num_uc_to_switch = 0;
912
vivek mehta4ed66e62016-04-15 23:33:34 -0700913 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
914
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700915 /*
916 * This function is to make sure that all the active capture usecases
917 * are always routed to the same input sound device.
918 * For example, if audio-record and voice-call usecases are currently
919 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
920 * is received for voice call then we have to make sure that audio-record
921 * usecase is also switched to earpiece i.e. voice-dmic-ef,
922 * because of the limitation that two devices cannot be enabled
923 * at the same time if they share the same backend.
924 */
925 for (i = 0; i < AUDIO_USECASE_MAX; i++)
926 switch_device[i] = false;
927
928 list_for_each(node, &adev->usecase_list) {
929 usecase = node_to_item(node, struct audio_usecase, list);
930 if (usecase->type != PCM_PLAYBACK &&
931 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700932 usecase->in_snd_device != snd_device &&
933 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700934 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
935 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700936 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700937 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 switch_device[usecase->id] = true;
939 num_uc_to_switch++;
940 }
941 }
942
943 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700944 list_for_each(node, &adev->usecase_list) {
945 usecase = node_to_item(node, struct audio_usecase, list);
946 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700947 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700948 }
949 }
950
951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
953 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700954 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700955 }
956 }
957
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700958 /* Re-route all the usecases on the shared backend other than the
959 specified usecase to new snd devices */
960 list_for_each(node, &adev->usecase_list) {
961 usecase = node_to_item(node, struct audio_usecase, list);
962 /* Update the in_snd_device only before enabling the audio route */
963 if (switch_device[usecase->id] ) {
964 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700965 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700966 }
967 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700968 }
969}
970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700972static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700974 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700975 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800976
977 switch (channels) {
978 /*
979 * Do not handle stereo output in Multi-channel cases
980 * Stereo case is handled in normal playback path
981 */
982 case 6:
983 ALOGV("%s: HDMI supports 5.1", __func__);
984 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
985 break;
986 case 8:
987 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
988 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
989 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
990 break;
991 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700992 ALOGE("HDMI does not support multi channel playback");
993 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994 break;
995 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700996 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997}
998
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700999static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1000 uint32_t *supported_sample_rates __unused,
1001 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001002{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001003 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1004 supported_sample_rates,
1005 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001006#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001007 for (ssize_t i=0; i<count; i++) {
1008 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1009 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010 }
1011#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001012 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001013}
1014
Haynes Mathew George569b7482017-05-08 14:44:27 -07001015static int read_usb_sup_channel_masks(bool is_playback,
1016 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001017 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001018{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001019 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001020 int channel_count;
1021 uint32_t num_masks = 0;
1022 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1023 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001024 }
Eric Laurent74b55762017-07-09 17:04:53 -07001025 if (is_playback) {
1026 // For playback we never report mono because the framework always outputs stereo
1027 channel_count = DEFAULT_CHANNEL_COUNT;
1028 // audio_channel_out_mask_from_count() does return positional masks for channel counts
1029 // above 2 but we want indexed masks here. So we
1030 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1031 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1032 }
1033 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1034 supported_channel_masks[num_masks++] =
1035 audio_channel_mask_for_index_assignment_from_count(channel_count);
1036 }
1037 } else {
1038 // For capture we report all supported channel masks from 1 channel up.
1039 channel_count = MIN_CHANNEL_COUNT;
1040 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1041 // indexed mask
1042 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1043 supported_channel_masks[num_masks++] =
1044 audio_channel_in_mask_from_count(channel_count);
1045 }
1046 }
1047 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1048 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1049 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001050}
1051
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001052static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001053 audio_format_t *supported_formats,
1054 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001055{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001056 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001057 switch (bitwidth) {
1058 case 24:
1059 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001060 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001061 break;
1062 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001063 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001064 break;
1065 case 16:
1066 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001067 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001068 break;
1069 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001070 ALOGV("%s: %s supported format %d", __func__,
1071 is_playback ? "P" : "C", bitwidth);
1072 return 1;
1073}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001074
Haynes Mathew George569b7482017-05-08 14:44:27 -07001075static int read_usb_sup_params_and_compare(bool is_playback,
1076 audio_format_t *format,
1077 audio_format_t *supported_formats,
1078 uint32_t max_formats,
1079 audio_channel_mask_t *mask,
1080 audio_channel_mask_t *supported_channel_masks,
1081 uint32_t max_masks,
1082 uint32_t *rate,
1083 uint32_t *supported_sample_rates,
1084 uint32_t max_rates) {
1085 int ret = 0;
1086 int num_formats;
1087 int num_masks;
1088 int num_rates;
1089 int i;
1090
1091 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1092 max_formats);
1093 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1094 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001095
Haynes Mathew George569b7482017-05-08 14:44:27 -07001096 num_rates = read_usb_sup_sample_rates(is_playback,
1097 supported_sample_rates, max_rates);
1098
1099#define LUT(table, len, what, dflt) \
1100 for (i=0; i<len && (table[i] != what); i++); \
1101 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1102
1103 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1104 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1105 LUT(supported_sample_rates, num_rates, *rate, 0);
1106
1107#undef LUT
1108 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001109}
1110
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001111static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1112{
1113 struct audio_usecase *usecase;
1114 struct listnode *node;
1115
1116 list_for_each(node, &adev->usecase_list) {
1117 usecase = node_to_item(node, struct audio_usecase, list);
1118 if (usecase->type == VOICE_CALL) {
1119 ALOGV("%s: usecase id %d", __func__, usecase->id);
1120 return usecase->id;
1121 }
1122 }
1123 return USECASE_INVALID;
1124}
1125
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001126struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1127 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128{
1129 struct audio_usecase *usecase;
1130 struct listnode *node;
1131
1132 list_for_each(node, &adev->usecase_list) {
1133 usecase = node_to_item(node, struct audio_usecase, list);
1134 if (usecase->id == uc_id)
1135 return usecase;
1136 }
1137 return NULL;
1138}
1139
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001140int select_devices(struct audio_device *adev,
1141 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001143 snd_device_t out_snd_device = SND_DEVICE_NONE;
1144 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001145 struct audio_usecase *usecase = NULL;
1146 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001147 struct audio_usecase *hfp_usecase = NULL;
1148 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001149 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001151
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 usecase = get_usecase_from_list(adev, uc_id);
1153 if (usecase == NULL) {
1154 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1155 return -EINVAL;
1156 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001157
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001158 if ((usecase->type == VOICE_CALL) ||
1159 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001160 out_snd_device = platform_get_output_snd_device(adev->platform,
1161 usecase->stream.out->devices);
1162 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001163 usecase->devices = usecase->stream.out->devices;
1164 } else {
1165 /*
1166 * If the voice call is active, use the sound devices of voice call usecase
1167 * so that it would not result any device switch. All the usecases will
1168 * be switched to new device when select_devices() is called for voice call
1169 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001170 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001172 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001173 vc_usecase = get_usecase_from_list(adev,
1174 get_voice_usecase_id_from_list(adev));
1175 if ((vc_usecase != NULL) &&
1176 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1177 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001178 in_snd_device = vc_usecase->in_snd_device;
1179 out_snd_device = vc_usecase->out_snd_device;
1180 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001181 } else if (audio_extn_hfp_is_active(adev)) {
1182 hfp_ucid = audio_extn_hfp_get_usecase();
1183 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1184 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1185 in_snd_device = hfp_usecase->in_snd_device;
1186 out_snd_device = hfp_usecase->out_snd_device;
1187 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001188 }
1189 if (usecase->type == PCM_PLAYBACK) {
1190 usecase->devices = usecase->stream.out->devices;
1191 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001192 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001193 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001195 if (usecase->stream.out == adev->primary_output &&
1196 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001197 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1198 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001199 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001200 select_devices(adev, adev->active_input->usecase);
1201 }
1202 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001203 } else if (usecase->type == PCM_CAPTURE) {
1204 usecase->devices = usecase->stream.in->device;
1205 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001206 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001207 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001208 if (adev->active_input &&
1209 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1210 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001211 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001212 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1213 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1214 } else if (adev->primary_output) {
1215 out_device = adev->primary_output->devices;
1216 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001217 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001218 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001219 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001220 }
1221 }
1222
1223 if (out_snd_device == usecase->out_snd_device &&
1224 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 return 0;
1226 }
1227
Eric Laurent2bafff12016-03-17 12:17:23 -07001228 if (out_snd_device != SND_DEVICE_NONE &&
1229 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1230 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1231 __func__,
1232 use_case_table[uc_id],
1233 adev->last_logged_snd_device[uc_id][0],
1234 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1235 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1236 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1237 -1,
1238 out_snd_device,
1239 platform_get_snd_device_name(out_snd_device),
1240 platform_get_snd_device_acdb_id(out_snd_device));
1241 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1242 }
1243 if (in_snd_device != SND_DEVICE_NONE &&
1244 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1245 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1246 __func__,
1247 use_case_table[uc_id],
1248 adev->last_logged_snd_device[uc_id][1],
1249 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1250 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1251 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1252 -1,
1253 in_snd_device,
1254 platform_get_snd_device_name(in_snd_device),
1255 platform_get_snd_device_acdb_id(in_snd_device));
1256 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1257 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001259 /*
1260 * Limitation: While in call, to do a device switch we need to disable
1261 * and enable both RX and TX devices though one of them is same as current
1262 * device.
1263 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001264 if ((usecase->type == VOICE_CALL) &&
1265 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1266 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001267 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001268 /* Disable sidetone only if voice call already exists */
1269 if (voice_is_call_state_active(adev))
1270 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001271 }
1272
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001273 /* Disable current sound devices */
1274 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001275 disable_audio_route(adev, usecase);
1276 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277 }
1278
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001279 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001280 disable_audio_route(adev, usecase);
1281 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001282 }
1283
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001284 /* Applicable only on the targets that has external modem.
1285 * New device information should be sent to modem before enabling
1286 * the devices to reduce in-call device switch time.
1287 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001288 if ((usecase->type == VOICE_CALL) &&
1289 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1290 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001291 status = platform_switch_voice_call_enable_device_config(adev->platform,
1292 out_snd_device,
1293 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001294 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001295
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296 /* Enable new sound devices */
1297 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001298 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001299 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001300 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001301 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302 }
1303
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001304 if (in_snd_device != SND_DEVICE_NONE) {
1305 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001306 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001307 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308
Eric Laurentb23d5282013-05-14 15:27:20 -07001309 if (usecase->type == VOICE_CALL)
1310 status = platform_switch_voice_call_device_post(adev->platform,
1311 out_snd_device,
1312 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001313
sangwoo170731f2013-06-08 15:36:36 +09001314 usecase->in_snd_device = in_snd_device;
1315 usecase->out_snd_device = out_snd_device;
1316
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001317 audio_extn_tfa_98xx_set_mode();
1318
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001319 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001320
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001321 /* Applicable only on the targets that has external modem.
1322 * Enable device command should be sent to modem only after
1323 * enabling voice call mixer controls
1324 */
vivek mehta765eb642015-08-07 19:46:06 -07001325 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001326 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1327 out_snd_device,
1328 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001329 /* Enable sidetone only if voice call already exists */
1330 if (voice_is_call_state_active(adev))
1331 voice_set_sidetone(adev, out_snd_device, true);
1332 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001333
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001334 return status;
1335}
1336
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001337static int stop_input_stream(struct stream_in *in)
1338{
1339 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340 struct audio_usecase *uc_info;
1341 struct audio_device *adev = in->dev;
1342
Eric Laurent994a6932013-07-17 11:51:42 -07001343 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001344 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001345
1346 if (adev->active_input) {
1347 if (adev->active_input->usecase == in->usecase) {
1348 adev->active_input = NULL;
1349 } else {
1350 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1351 __func__,
1352 use_case_table[adev->active_input->usecase],
1353 use_case_table[in->usecase]);
1354 }
1355 }
1356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001357 uc_info = get_usecase_from_list(adev, in->usecase);
1358 if (uc_info == NULL) {
1359 ALOGE("%s: Could not find the usecase (%d) in the list",
1360 __func__, in->usecase);
1361 return -EINVAL;
1362 }
1363
vivek mehta781065c2017-04-04 12:55:01 -07001364 /* Close in-call recording streams */
1365 voice_check_and_stop_incall_rec_usecase(adev, in);
1366
Eric Laurent150dbfe2013-02-27 14:31:02 -08001367 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001368 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001369
1370 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001371 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001373 list_remove(&uc_info->list);
1374 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375
Eric Laurent994a6932013-07-17 11:51:42 -07001376 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001377 return ret;
1378}
1379
1380int start_input_stream(struct stream_in *in)
1381{
1382 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001383 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384 struct audio_usecase *uc_info;
1385 struct audio_device *adev = in->dev;
1386
Eric Laurent994a6932013-07-17 11:51:42 -07001387 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001388
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001389 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1390 return -EIO;
1391
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001392 if (in->card_status == CARD_STATUS_OFFLINE ||
1393 adev->card_status == CARD_STATUS_OFFLINE) {
1394 ALOGW("in->card_status or adev->card_status offline, try again");
1395 ret = -EAGAIN;
1396 goto error_config;
1397 }
1398
vivek mehta781065c2017-04-04 12:55:01 -07001399 /* Check if source matches incall recording usecase criteria */
1400 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1401 if (ret)
1402 goto error_config;
1403 else
1404 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1405
Eric Laurentb23d5282013-05-14 15:27:20 -07001406 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001407 if (in->pcm_device_id < 0) {
1408 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1409 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001410 ret = -EINVAL;
1411 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001412 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001413
1414 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001415 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1416 uc_info->id = in->usecase;
1417 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001418 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001419 uc_info->devices = in->device;
1420 uc_info->in_snd_device = SND_DEVICE_NONE;
1421 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001422
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001423 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001424
1425 audio_extn_perf_lock_acquire();
1426
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001427 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001428
Eric Laurent0e46adf2016-12-16 12:49:24 -08001429 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001430 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001431 ALOGE("%s: pcm stream not ready", __func__);
1432 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001433 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001434 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001435 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001436 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1437 goto error_open;
1438 }
1439 } else {
1440 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1441 unsigned int pcm_open_retry_count = 0;
1442
1443 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1444 flags |= PCM_MMAP | PCM_NOIRQ;
1445 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1446 } else if (in->realtime) {
1447 flags |= PCM_MMAP | PCM_NOIRQ;
1448 }
1449
1450 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1451 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1452
1453 while (1) {
1454 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1455 flags, &in->config);
1456 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1457 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1458 if (in->pcm != NULL) {
1459 pcm_close(in->pcm);
1460 in->pcm = NULL;
1461 }
1462 if (pcm_open_retry_count-- == 0) {
1463 ret = -EIO;
1464 goto error_open;
1465 }
1466 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1467 continue;
1468 }
1469 break;
1470 }
1471
1472 ALOGV("%s: pcm_prepare", __func__);
1473 ret = pcm_prepare(in->pcm);
1474 if (ret < 0) {
1475 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001476 pcm_close(in->pcm);
1477 in->pcm = NULL;
1478 goto error_open;
1479 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001480 if (in->realtime) {
1481 ret = pcm_start(in->pcm);
1482 if (ret < 0) {
1483 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1484 pcm_close(in->pcm);
1485 in->pcm = NULL;
1486 goto error_open;
1487 }
1488 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001489 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001490 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001491 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001492 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001493
Eric Laurent0e46adf2016-12-16 12:49:24 -08001494 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001495
1496error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001498 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001499
1500error_config:
1501 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001502 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001503 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001504}
1505
Eric Laurenta1478072015-09-21 17:21:52 -07001506void lock_input_stream(struct stream_in *in)
1507{
1508 pthread_mutex_lock(&in->pre_lock);
1509 pthread_mutex_lock(&in->lock);
1510 pthread_mutex_unlock(&in->pre_lock);
1511}
1512
1513void lock_output_stream(struct stream_out *out)
1514{
1515 pthread_mutex_lock(&out->pre_lock);
1516 pthread_mutex_lock(&out->lock);
1517 pthread_mutex_unlock(&out->pre_lock);
1518}
1519
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001520/* must be called with out->lock locked */
1521static int send_offload_cmd_l(struct stream_out* out, int command)
1522{
1523 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1524
1525 ALOGVV("%s %d", __func__, command);
1526
1527 cmd->cmd = command;
1528 list_add_tail(&out->offload_cmd_list, &cmd->node);
1529 pthread_cond_signal(&out->offload_cond);
1530 return 0;
1531}
1532
1533/* must be called iwth out->lock locked */
1534static void stop_compressed_output_l(struct stream_out *out)
1535{
1536 out->offload_state = OFFLOAD_STATE_IDLE;
1537 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001538 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001539 if (out->compr != NULL) {
1540 compress_stop(out->compr);
1541 while (out->offload_thread_blocked) {
1542 pthread_cond_wait(&out->cond, &out->lock);
1543 }
1544 }
1545}
1546
1547static void *offload_thread_loop(void *context)
1548{
1549 struct stream_out *out = (struct stream_out *) context;
1550 struct listnode *item;
1551
1552 out->offload_state = OFFLOAD_STATE_IDLE;
1553 out->playback_started = 0;
1554
1555 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1556 set_sched_policy(0, SP_FOREGROUND);
1557 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1558
1559 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001560 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001561 for (;;) {
1562 struct offload_cmd *cmd = NULL;
1563 stream_callback_event_t event;
1564 bool send_callback = false;
1565
1566 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1567 __func__, list_empty(&out->offload_cmd_list),
1568 out->offload_state);
1569 if (list_empty(&out->offload_cmd_list)) {
1570 ALOGV("%s SLEEPING", __func__);
1571 pthread_cond_wait(&out->offload_cond, &out->lock);
1572 ALOGV("%s RUNNING", __func__);
1573 continue;
1574 }
1575
1576 item = list_head(&out->offload_cmd_list);
1577 cmd = node_to_item(item, struct offload_cmd, node);
1578 list_remove(item);
1579
1580 ALOGVV("%s STATE %d CMD %d out->compr %p",
1581 __func__, out->offload_state, cmd->cmd, out->compr);
1582
1583 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1584 free(cmd);
1585 break;
1586 }
1587
1588 if (out->compr == NULL) {
1589 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001590 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001591 pthread_cond_signal(&out->cond);
1592 continue;
1593 }
1594 out->offload_thread_blocked = true;
1595 pthread_mutex_unlock(&out->lock);
1596 send_callback = false;
1597 switch(cmd->cmd) {
1598 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1599 compress_wait(out->compr, -1);
1600 send_callback = true;
1601 event = STREAM_CBK_EVENT_WRITE_READY;
1602 break;
1603 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001604 compress_next_track(out->compr);
1605 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001606 send_callback = true;
1607 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001608 /* Resend the metadata for next iteration */
1609 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001610 break;
1611 case OFFLOAD_CMD_DRAIN:
1612 compress_drain(out->compr);
1613 send_callback = true;
1614 event = STREAM_CBK_EVENT_DRAIN_READY;
1615 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001616 case OFFLOAD_CMD_ERROR:
1617 send_callback = true;
1618 event = STREAM_CBK_EVENT_ERROR;
1619 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001620 default:
1621 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1622 break;
1623 }
Eric Laurenta1478072015-09-21 17:21:52 -07001624 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001625 out->offload_thread_blocked = false;
1626 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001627 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001628 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001629 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001630 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001631 free(cmd);
1632 }
1633
1634 pthread_cond_signal(&out->cond);
1635 while (!list_empty(&out->offload_cmd_list)) {
1636 item = list_head(&out->offload_cmd_list);
1637 list_remove(item);
1638 free(node_to_item(item, struct offload_cmd, node));
1639 }
1640 pthread_mutex_unlock(&out->lock);
1641
1642 return NULL;
1643}
1644
1645static int create_offload_callback_thread(struct stream_out *out)
1646{
1647 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1648 list_init(&out->offload_cmd_list);
1649 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1650 offload_thread_loop, out);
1651 return 0;
1652}
1653
1654static int destroy_offload_callback_thread(struct stream_out *out)
1655{
Eric Laurenta1478072015-09-21 17:21:52 -07001656 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001657 stop_compressed_output_l(out);
1658 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1659
1660 pthread_mutex_unlock(&out->lock);
1661 pthread_join(out->offload_thread, (void **) NULL);
1662 pthread_cond_destroy(&out->offload_cond);
1663
1664 return 0;
1665}
1666
Eric Laurent07eeafd2013-10-06 12:52:49 -07001667static bool allow_hdmi_channel_config(struct audio_device *adev)
1668{
1669 struct listnode *node;
1670 struct audio_usecase *usecase;
1671 bool ret = true;
1672
1673 list_for_each(node, &adev->usecase_list) {
1674 usecase = node_to_item(node, struct audio_usecase, list);
1675 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1676 /*
1677 * If voice call is already existing, do not proceed further to avoid
1678 * disabling/enabling both RX and TX devices, CSD calls, etc.
1679 * Once the voice call done, the HDMI channels can be configured to
1680 * max channels of remaining use cases.
1681 */
1682 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001683 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001684 __func__);
1685 ret = false;
1686 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001687 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1688 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001689 "no change in HDMI channels", __func__);
1690 ret = false;
1691 break;
1692 }
1693 }
1694 }
1695 return ret;
1696}
1697
1698static int check_and_set_hdmi_channels(struct audio_device *adev,
1699 unsigned int channels)
1700{
1701 struct listnode *node;
1702 struct audio_usecase *usecase;
1703
1704 /* Check if change in HDMI channel config is allowed */
1705 if (!allow_hdmi_channel_config(adev))
1706 return 0;
1707
1708 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001709 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001710 return 0;
1711 }
1712
1713 platform_set_hdmi_channels(adev->platform, channels);
1714 adev->cur_hdmi_channels = channels;
1715
1716 /*
1717 * Deroute all the playback streams routed to HDMI so that
1718 * the back end is deactivated. Note that backend will not
1719 * be deactivated if any one stream is connected to it.
1720 */
1721 list_for_each(node, &adev->usecase_list) {
1722 usecase = node_to_item(node, struct audio_usecase, list);
1723 if (usecase->type == PCM_PLAYBACK &&
1724 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001725 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001726 }
1727 }
1728
1729 /*
1730 * Enable all the streams disabled above. Now the HDMI backend
1731 * will be activated with new channel configuration
1732 */
1733 list_for_each(node, &adev->usecase_list) {
1734 usecase = node_to_item(node, struct audio_usecase, list);
1735 if (usecase->type == PCM_PLAYBACK &&
1736 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001737 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001738 }
1739 }
1740
1741 return 0;
1742}
1743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744static int stop_output_stream(struct stream_out *out)
1745{
1746 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 struct audio_usecase *uc_info;
1748 struct audio_device *adev = out->dev;
1749
Eric Laurent994a6932013-07-17 11:51:42 -07001750 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001751 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752 uc_info = get_usecase_from_list(adev, out->usecase);
1753 if (uc_info == NULL) {
1754 ALOGE("%s: Could not find the usecase (%d) in the list",
1755 __func__, out->usecase);
1756 return -EINVAL;
1757 }
1758
Haynes Mathew George41f86652014-06-17 14:22:15 -07001759 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1760 if (adev->visualizer_stop_output != NULL)
1761 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1762 if (adev->offload_effects_stop_output != NULL)
1763 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1764 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001765
Eric Laurent150dbfe2013-02-27 14:31:02 -08001766 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001767 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001768
1769 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001770 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001772 list_remove(&uc_info->list);
1773 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774
Eric Laurent0499d4f2014-08-25 22:39:29 -05001775 audio_extn_extspk_update(adev->extspk);
1776
Eric Laurent07eeafd2013-10-06 12:52:49 -07001777 /* Must be called after removing the usecase from list */
1778 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1779 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1780
Eric Laurent994a6932013-07-17 11:51:42 -07001781 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782 return ret;
1783}
1784
1785int start_output_stream(struct stream_out *out)
1786{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001787 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 struct audio_usecase *uc_info;
1789 struct audio_device *adev = out->dev;
1790
Eric Laurent994a6932013-07-17 11:51:42 -07001791 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001792 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001793
1794 if (out->card_status == CARD_STATUS_OFFLINE ||
1795 adev->card_status == CARD_STATUS_OFFLINE) {
1796 ALOGW("out->card_status or adev->card_status offline, try again");
1797 ret = -EAGAIN;
1798 goto error_config;
1799 }
1800
Eric Laurentb23d5282013-05-14 15:27:20 -07001801 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802 if (out->pcm_device_id < 0) {
1803 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1804 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001805 ret = -EINVAL;
1806 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001807 }
1808
1809 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1810 uc_info->id = out->usecase;
1811 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001812 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001813 uc_info->devices = out->devices;
1814 uc_info->in_snd_device = SND_DEVICE_NONE;
1815 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001816
Eric Laurent07eeafd2013-10-06 12:52:49 -07001817 /* This must be called before adding this usecase to the list */
1818 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1819 check_and_set_hdmi_channels(adev, out->config.channels);
1820
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001821 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001823 audio_extn_perf_lock_acquire();
1824
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001825 select_devices(adev, out->usecase);
1826
Eric Laurent0499d4f2014-08-25 22:39:29 -05001827 audio_extn_extspk_update(adev->extspk);
1828
Andy Hung31aca912014-03-20 17:14:59 -07001829 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001830 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001831 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1832 out->pcm = NULL;
1833 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1834 COMPRESS_IN, &out->compr_config);
1835 if (out->compr && !is_compress_ready(out->compr)) {
1836 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1837 compress_close(out->compr);
1838 out->compr = NULL;
1839 ret = -EIO;
1840 goto error_open;
1841 }
1842 if (out->offload_callback)
1843 compress_nonblock(out->compr, out->non_blocking);
1844
1845 if (adev->visualizer_start_output != NULL)
1846 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1847 if (adev->offload_effects_start_output != NULL)
1848 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1849 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001850 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001851 ALOGE("%s: pcm stream not ready", __func__);
1852 goto error_open;
1853 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001854 ret = pcm_start(out->pcm);
1855 if (ret < 0) {
1856 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1857 goto error_open;
1858 }
1859 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001860 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001861 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001862
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001863 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1864 flags |= PCM_MMAP | PCM_NOIRQ;
1865 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001866 } else if (out->realtime) {
1867 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001868 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001869
1870 while (1) {
1871 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1872 flags, &out->config);
1873 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1874 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1875 if (out->pcm != NULL) {
1876 pcm_close(out->pcm);
1877 out->pcm = NULL;
1878 }
1879 if (pcm_open_retry_count-- == 0) {
1880 ret = -EIO;
1881 goto error_open;
1882 }
1883 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1884 continue;
1885 }
1886 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001887 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001888 ALOGV("%s: pcm_prepare", __func__);
1889 if (pcm_is_ready(out->pcm)) {
1890 ret = pcm_prepare(out->pcm);
1891 if (ret < 0) {
1892 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1893 pcm_close(out->pcm);
1894 out->pcm = NULL;
1895 goto error_open;
1896 }
1897 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001898 if (out->realtime) {
1899 ret = pcm_start(out->pcm);
1900 if (ret < 0) {
1901 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1902 pcm_close(out->pcm);
1903 out->pcm = NULL;
1904 goto error_open;
1905 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001906 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001907 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001908 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001909 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001910 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001911 audio_extn_utils_send_app_type_gain(out->dev,
1912 out->app_type_cfg.app_type,
1913 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001914
1915 // consider a scenario where on pause lower layers are tear down.
1916 // so on resume, swap mixer control need to be sent only when
1917 // backend is active, hence rather than sending from enable device
1918 // sending it from start of streamtream
1919
1920 platform_set_swap_channels(adev, true);
1921
Eric Laurent994a6932013-07-17 11:51:42 -07001922 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001923 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001924error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001925 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001927error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001928 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929}
1930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931static int check_input_parameters(uint32_t sample_rate,
1932 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07001933 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001935 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1936 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07001937 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
1938 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07001939 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1940 return -EINVAL;
1941 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942
Eric Laurent74b55762017-07-09 17:04:53 -07001943 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
1944 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001945 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07001946 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07001947 return -EINVAL;
1948 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949
1950 switch (sample_rate) {
1951 case 8000:
1952 case 11025:
1953 case 12000:
1954 case 16000:
1955 case 22050:
1956 case 24000:
1957 case 32000:
1958 case 44100:
1959 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001960 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 break;
1962 default:
vivek mehtadae44712015-07-27 14:13:18 -07001963 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964 return -EINVAL;
1965 }
1966
1967 return 0;
1968}
1969
vivek mehtaa68fea62017-06-08 19:04:02 -07001970static size_t get_stream_buffer_size(size_t duration_ms,
1971 uint32_t sample_rate,
1972 audio_format_t format,
1973 int channel_count,
1974 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975{
1976 size_t size = 0;
1977
vivek mehtaa68fea62017-06-08 19:04:02 -07001978 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001979 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001980 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001981
1982 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983
Glenn Kasten4f993392014-05-14 07:30:48 -07001984 /* make sure the size is multiple of 32 bytes
1985 * At 48 kHz mono 16-bit PCM:
1986 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1987 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1988 */
1989 size += 0x1f;
1990 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001991
1992 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993}
1994
1995static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1996{
1997 struct stream_out *out = (struct stream_out *)stream;
1998
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001999 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000}
2001
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002002static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003{
2004 return -ENOSYS;
2005}
2006
2007static size_t out_get_buffer_size(const struct audio_stream *stream)
2008{
2009 struct stream_out *out = (struct stream_out *)stream;
2010
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002011 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2012 return out->compr_config.fragment_size;
2013 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002014 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002015 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016}
2017
2018static uint32_t out_get_channels(const struct audio_stream *stream)
2019{
2020 struct stream_out *out = (struct stream_out *)stream;
2021
2022 return out->channel_mask;
2023}
2024
2025static audio_format_t out_get_format(const struct audio_stream *stream)
2026{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002027 struct stream_out *out = (struct stream_out *)stream;
2028
2029 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030}
2031
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002032static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033{
2034 return -ENOSYS;
2035}
2036
2037static int out_standby(struct audio_stream *stream)
2038{
2039 struct stream_out *out = (struct stream_out *)stream;
2040 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002041 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042
Eric Laurent994a6932013-07-17 11:51:42 -07002043 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002044 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002045
Eric Laurenta1478072015-09-21 17:21:52 -07002046 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002048 if (adev->adm_deregister_stream)
2049 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002050 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2053 if (out->pcm) {
2054 pcm_close(out->pcm);
2055 out->pcm = NULL;
2056 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002057 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002058 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002059 out->playback_started = false;
2060 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002061 } else {
2062 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002063 out->gapless_mdata.encoder_delay = 0;
2064 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002065 if (out->compr != NULL) {
2066 compress_close(out->compr);
2067 out->compr = NULL;
2068 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002069 }
Phil Burkbc991042017-02-24 08:06:44 -08002070 if (do_stop) {
2071 stop_output_stream(out);
2072 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002073 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074 }
2075 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002076 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077 return 0;
2078}
2079
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002080static int out_on_error(struct audio_stream *stream)
2081{
2082 struct stream_out *out = (struct stream_out *)stream;
2083 struct audio_device *adev = out->dev;
2084 bool do_standby = false;
2085
2086 lock_output_stream(out);
2087 if (!out->standby) {
2088 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2089 stop_compressed_output_l(out);
2090 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2091 } else
2092 do_standby = true;
2093 }
2094 pthread_mutex_unlock(&out->lock);
2095
2096 if (do_standby)
2097 return out_standby(&out->stream.common);
2098
2099 return 0;
2100}
2101
Andy Hung7401c7c2016-09-21 12:41:21 -07002102static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103{
Andy Hung7401c7c2016-09-21 12:41:21 -07002104 struct stream_out *out = (struct stream_out *)stream;
2105
2106 // We try to get the lock for consistency,
2107 // but it isn't necessary for these variables.
2108 // If we're not in standby, we may be blocked on a write.
2109 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2110 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2111 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2112
2113 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002114 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002115 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002116
2117 // dump error info
2118 (void)error_log_dump(
2119 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121 return 0;
2122}
2123
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002124static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2125{
2126 int ret = 0;
2127 char value[32];
2128 struct compr_gapless_mdata tmp_mdata;
2129
2130 if (!out || !parms) {
2131 return -EINVAL;
2132 }
2133
2134 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2135 if (ret >= 0) {
2136 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2137 } else {
2138 return -EINVAL;
2139 }
2140
2141 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2142 if (ret >= 0) {
2143 tmp_mdata.encoder_padding = atoi(value);
2144 } else {
2145 return -EINVAL;
2146 }
2147
2148 out->gapless_mdata = tmp_mdata;
2149 out->send_new_metadata = 1;
2150 ALOGV("%s new encoder delay %u and padding %u", __func__,
2151 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2152
2153 return 0;
2154}
2155
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002156static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2157{
2158 return out == adev->primary_output || out == adev->voice_tx_output;
2159}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2162{
2163 struct stream_out *out = (struct stream_out *)stream;
2164 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002165 struct audio_usecase *usecase;
2166 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 struct str_parms *parms;
2168 char value[32];
2169 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002170 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002171 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172
Eric Laurent2e140aa2016-06-30 17:14:46 -07002173 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002174 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002175 parms = str_parms_create_str(kvpairs);
2176 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2177 if (ret >= 0) {
2178 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002179 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002180 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002181
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002182 /*
2183 * When HDMI cable is unplugged the music playback is paused and
2184 * the policy manager sends routing=0. But the audioflinger
2185 * continues to write data until standby time (3sec).
2186 * As the HDMI core is turned off, the write gets blocked.
2187 * Avoid this by routing audio to speaker until standby.
2188 */
2189 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2190 val == AUDIO_DEVICE_NONE) {
2191 val = AUDIO_DEVICE_OUT_SPEAKER;
2192 }
2193
2194 /*
2195 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002196 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002197 * the select_devices(). But how do we undo this?
2198 *
2199 * For example, music playback is active on headset (deep-buffer usecase)
2200 * and if we go to ringtones and select a ringtone, low-latency usecase
2201 * will be started on headset+speaker. As we can't enable headset+speaker
2202 * and headset devices at the same time, select_devices() switches the music
2203 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2204 * So when the ringtone playback is completed, how do we undo the same?
2205 *
2206 * We are relying on the out_set_parameters() call on deep-buffer output,
2207 * once the ringtone playback is ended.
2208 * NOTE: We should not check if the current devices are same as new devices.
2209 * Because select_devices() must be called to switch back the music
2210 * playback to headset.
2211 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002212 audio_devices_t new_dev = val;
2213 if (new_dev != AUDIO_DEVICE_NONE) {
2214 bool same_dev = out->devices == new_dev;
2215 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002216
Eric Laurenta7657192014-10-09 21:09:33 -07002217 if (output_drives_call(adev, out)) {
2218 if (!voice_is_in_call(adev)) {
2219 if (adev->mode == AUDIO_MODE_IN_CALL) {
2220 adev->current_call_output = out;
2221 ret = voice_start_call(adev);
2222 }
2223 } else {
2224 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002225 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002226 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002227 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002228
2229 if (!out->standby) {
2230 if (!same_dev) {
2231 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002232 // inform adm before actual routing to prevent glitches.
2233 if (adev->adm_on_routing_change) {
2234 adev->adm_on_routing_change(adev->adm_data,
2235 out->handle);
2236 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002237 }
2238 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002239 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002240
2241 // on device switch force swap, lower functions will make sure
2242 // to check if swap is allowed or not.
2243
2244 if (!same_dev)
2245 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002246 }
2247
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002248 }
2249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002251 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002252
2253 /*handles device and call state changes*/
2254 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002256
2257 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2258 parse_compress_metadata(out, parms);
2259 }
2260
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002262 ALOGV("%s: exit: code(%d)", __func__, status);
2263 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002264}
2265
Haynes Mathew George569b7482017-05-08 14:44:27 -07002266static bool stream_get_parameter_channels(struct str_parms *query,
2267 struct str_parms *reply,
2268 audio_channel_mask_t *supported_channel_masks) {
2269 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002272 size_t i, j;
2273
2274 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2275 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276 value[0] = '\0';
2277 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002278 while (supported_channel_masks[i] != 0) {
2279 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2280 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 if (!first) {
2282 strcat(value, "|");
2283 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002284 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285 first = false;
2286 break;
2287 }
2288 }
2289 i++;
2290 }
2291 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002292 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002293 return ret >= 0;
2294}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002295
Haynes Mathew George569b7482017-05-08 14:44:27 -07002296static bool stream_get_parameter_formats(struct str_parms *query,
2297 struct str_parms *reply,
2298 audio_format_t *supported_formats) {
2299 int ret = -1;
2300 char value[256];
2301 int i;
2302
2303 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2304 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002305 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002306 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002307 case AUDIO_FORMAT_PCM_16_BIT:
2308 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2309 break;
2310 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2311 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2312 break;
2313 case AUDIO_FORMAT_PCM_32_BIT:
2314 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2315 break;
2316 default:
2317 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002318 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002319 break;
2320 }
2321 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002322 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002323 return ret >= 0;
2324}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002325
Haynes Mathew George569b7482017-05-08 14:44:27 -07002326static bool stream_get_parameter_rates(struct str_parms *query,
2327 struct str_parms *reply,
2328 uint32_t *supported_sample_rates) {
2329
2330 int i;
2331 char value[256];
2332 int ret = -1;
2333 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2334 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002335 value[0] = '\0';
2336 i=0;
2337 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002338 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002339 int avail = sizeof(value) - cursor;
2340 ret = snprintf(value + cursor, avail, "%s%d",
2341 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002342 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002343 if (ret < 0 || ret >= avail) {
2344 // if cursor is at the last element of the array
2345 // overwrite with \0 is duplicate work as
2346 // snprintf already put a \0 in place.
2347 // else
2348 // we had space to write the '|' at value[cursor]
2349 // (which will be overwritten) or no space to fill
2350 // the first element (=> cursor == 0)
2351 value[cursor] = '\0';
2352 break;
2353 }
2354 cursor += ret;
2355 ++i;
2356 }
2357 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2358 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002359 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002360 return ret >= 0;
2361}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002362
Haynes Mathew George569b7482017-05-08 14:44:27 -07002363static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2364{
2365 struct stream_out *out = (struct stream_out *)stream;
2366 struct str_parms *query = str_parms_create_str(keys);
2367 char *str;
2368 struct str_parms *reply = str_parms_create();
2369 bool replied = false;
2370 ALOGV("%s: enter: keys - %s", __func__, keys);
2371
2372 replied |= stream_get_parameter_channels(query, reply,
2373 &out->supported_channel_masks[0]);
2374 replied |= stream_get_parameter_formats(query, reply,
2375 &out->supported_formats[0]);
2376 replied |= stream_get_parameter_rates(query, reply,
2377 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002378 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002379 str = str_parms_to_str(reply);
2380 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002381 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 }
2383 str_parms_destroy(query);
2384 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002385 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386 return str;
2387}
2388
2389static uint32_t out_get_latency(const struct audio_stream_out *stream)
2390{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002391 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002392 struct stream_out *out = (struct stream_out *)stream;
2393
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002394 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2395 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002396 else if ((out->realtime) ||
2397 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002398 // since the buffer won't be filled up faster than realtime,
2399 // return a smaller number
2400 period_ms = (out->af_period_multiplier * out->config.period_size *
2401 1000) / (out->config.rate);
2402 hw_delay = platform_render_latency(out->usecase)/1000;
2403 return period_ms + hw_delay;
2404 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002405
2406 return (out->config.period_count * out->config.period_size * 1000) /
2407 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002408}
2409
2410static int out_set_volume(struct audio_stream_out *stream, float left,
2411 float right)
2412{
Eric Laurenta9024de2013-04-04 09:19:12 -07002413 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002414 int volume[2];
2415
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002416 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002417 /* only take left channel into account: the API is for stereo anyway */
2418 out->muted = (left == 0.0f);
2419 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002420 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2421 const char *mixer_ctl_name = "Compress Playback Volume";
2422 struct audio_device *adev = out->dev;
2423 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002424 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2425 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002426 /* try with the control based on device id */
2427 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2428 PCM_PLAYBACK);
2429 char ctl_name[128] = {0};
2430 snprintf(ctl_name, sizeof(ctl_name),
2431 "Compress Playback %d Volume", pcm_device_id);
2432 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2433 if (!ctl) {
2434 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2435 return -EINVAL;
2436 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 }
2438 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2439 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2440 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2441 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002442 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002443 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2444 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2445 if (!out->standby) {
2446 // if in standby, cached volume will be sent after stream is opened
2447 audio_extn_utils_send_app_type_gain(out->dev,
2448 out->app_type_cfg.app_type,
2449 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002450 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002451 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002452 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454 return -ENOSYS;
2455}
2456
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002457// note: this call is safe only if the stream_cb is
2458// removed first in close_output_stream (as is done now).
2459static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2460{
2461 if (!stream || !parms)
2462 return;
2463
2464 struct stream_out *out = (struct stream_out *)stream;
2465 struct audio_device *adev = out->dev;
2466
2467 card_status_t status;
2468 int card;
2469 if (parse_snd_card_status(parms, &card, &status) < 0)
2470 return;
2471
2472 pthread_mutex_lock(&adev->lock);
2473 bool valid_cb = (card == adev->snd_card);
2474 pthread_mutex_unlock(&adev->lock);
2475
2476 if (!valid_cb)
2477 return;
2478
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002479 lock_output_stream(out);
2480 if (out->card_status != status)
2481 out->card_status = status;
2482 pthread_mutex_unlock(&out->lock);
2483
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002484 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2485 use_case_table[out->usecase],
2486 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2487
2488 if (status == CARD_STATUS_OFFLINE)
2489 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002490
2491 return;
2492}
2493
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002494#ifdef NO_AUDIO_OUT
2495static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002496 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002497{
2498 struct stream_out *out = (struct stream_out *)stream;
2499
2500 /* No Output device supported other than BT for playback.
2501 * Sleep for the amount of buffer duration
2502 */
Eric Laurenta1478072015-09-21 17:21:52 -07002503 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002504 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2505 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002506 out_get_sample_rate(&out->stream.common));
2507 pthread_mutex_unlock(&out->lock);
2508 return bytes;
2509}
2510#endif
2511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2513 size_t bytes)
2514{
2515 struct stream_out *out = (struct stream_out *)stream;
2516 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002517 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002518 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002519
Eric Laurenta1478072015-09-21 17:21:52 -07002520 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002521 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002522 const size_t frame_size = audio_stream_out_frame_size(stream);
2523 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002524
Eric Laurent0e46adf2016-12-16 12:49:24 -08002525 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2526 error_code = ERROR_CODE_WRITE;
2527 goto exit;
2528 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002530 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002531 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002533 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002536 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 goto exit;
2538 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002539
2540 if (last_known_cal_step != -1) {
2541 ALOGD("%s: retry previous failed cal level set", __func__);
2542 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002546 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002547 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002548 if (out->send_new_metadata) {
2549 ALOGVV("send new gapless metadata");
2550 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2551 out->send_new_metadata = 0;
2552 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002553 unsigned int avail;
2554 struct timespec tstamp;
2555 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2556 /* Do not limit write size if the available frames count is unknown */
2557 if (ret != 0) {
2558 avail = bytes;
2559 }
2560 if (avail == 0) {
2561 ret = 0;
2562 } else {
2563 if (avail > bytes) {
2564 avail = bytes;
2565 }
2566 ret = compress_write(out->compr, buffer, avail);
2567 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2568 __func__, avail, ret);
2569 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002570
Eric Laurent6e895242013-09-05 16:10:57 -07002571 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002572 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2573 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002574 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002575 compress_start(out->compr);
2576 out->playback_started = 1;
2577 out->offload_state = OFFLOAD_STATE_PLAYING;
2578 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002579 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002580 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002581 } else {
2582 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002583 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002584 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002585 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002586 return ret;
2587 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002588 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 if (out->pcm) {
2590 if (out->muted)
2591 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002592
Eric Laurent0e46adf2016-12-16 12:49:24 -08002593 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002594
Haynes Mathew George03c40102016-01-29 17:57:48 -08002595 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2596 out->config.rate;
2597 request_out_focus(out, ns);
2598
2599 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2600 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002601 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002602 else
2603 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002604
Haynes Mathew George03c40102016-01-29 17:57:48 -08002605 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002606 } else {
2607 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002608 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 }
2610
2611exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002612 // For PCM we always consume the buffer and return #bytes regardless of ret.
2613 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002614 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002615 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002616 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002617
Andy Hung7401c7c2016-09-21 12:41:21 -07002618 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002619 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002620 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2621 ALOGE_IF(out->pcm != NULL,
2622 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002623 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002624 // usleep not guaranteed for values over 1 second but we don't limit here.
2625 }
2626 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628 pthread_mutex_unlock(&out->lock);
2629
2630 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002631 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002632 if (sleeptime_us != 0)
2633 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634 }
2635 return bytes;
2636}
2637
2638static int out_get_render_position(const struct audio_stream_out *stream,
2639 uint32_t *dsp_frames)
2640{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002641 struct stream_out *out = (struct stream_out *)stream;
2642 *dsp_frames = 0;
2643 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002644 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002645 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002646 unsigned long frames = 0;
2647 // TODO: check return value
2648 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2649 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002650 ALOGVV("%s rendered frames %d sample_rate %d",
2651 __func__, *dsp_frames, out->sample_rate);
2652 }
2653 pthread_mutex_unlock(&out->lock);
2654 return 0;
2655 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002656 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657}
2658
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002659static int out_add_audio_effect(const struct audio_stream *stream __unused,
2660 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661{
2662 return 0;
2663}
2664
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002665static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2666 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667{
2668 return 0;
2669}
2670
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002671static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2672 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002674 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675}
2676
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002677static int out_get_presentation_position(const struct audio_stream_out *stream,
2678 uint64_t *frames, struct timespec *timestamp)
2679{
2680 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002681 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002682 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002683
Eric Laurenta1478072015-09-21 17:21:52 -07002684 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002685
Eric Laurent949a0892013-09-20 09:20:13 -07002686 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2687 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002688 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002689 compress_get_tstamp(out->compr, &dsp_frames,
2690 &out->sample_rate);
2691 ALOGVV("%s rendered frames %ld sample_rate %d",
2692 __func__, dsp_frames, out->sample_rate);
2693 *frames = dsp_frames;
2694 ret = 0;
2695 /* this is the best we can do */
2696 clock_gettime(CLOCK_MONOTONIC, timestamp);
2697 }
2698 } else {
2699 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002700 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002701 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2702 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002703 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002704 // This adjustment accounts for buffering after app processor.
2705 // It is based on estimated DSP latency per use case, rather than exact.
2706 signed_frames -=
2707 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2708
Eric Laurent949a0892013-09-20 09:20:13 -07002709 // It would be unusual for this value to be negative, but check just in case ...
2710 if (signed_frames >= 0) {
2711 *frames = signed_frames;
2712 ret = 0;
2713 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002714 }
2715 }
2716 }
2717
2718 pthread_mutex_unlock(&out->lock);
2719
2720 return ret;
2721}
2722
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002723static int out_set_callback(struct audio_stream_out *stream,
2724 stream_callback_t callback, void *cookie)
2725{
2726 struct stream_out *out = (struct stream_out *)stream;
2727
2728 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002729 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002730 out->offload_callback = callback;
2731 out->offload_cookie = cookie;
2732 pthread_mutex_unlock(&out->lock);
2733 return 0;
2734}
2735
2736static int out_pause(struct audio_stream_out* stream)
2737{
2738 struct stream_out *out = (struct stream_out *)stream;
2739 int status = -ENOSYS;
2740 ALOGV("%s", __func__);
2741 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002742 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002743 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2744 status = compress_pause(out->compr);
2745 out->offload_state = OFFLOAD_STATE_PAUSED;
2746 }
2747 pthread_mutex_unlock(&out->lock);
2748 }
2749 return status;
2750}
2751
2752static int out_resume(struct audio_stream_out* stream)
2753{
2754 struct stream_out *out = (struct stream_out *)stream;
2755 int status = -ENOSYS;
2756 ALOGV("%s", __func__);
2757 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2758 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002759 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002760 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2761 status = compress_resume(out->compr);
2762 out->offload_state = OFFLOAD_STATE_PLAYING;
2763 }
2764 pthread_mutex_unlock(&out->lock);
2765 }
2766 return status;
2767}
2768
2769static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2770{
2771 struct stream_out *out = (struct stream_out *)stream;
2772 int status = -ENOSYS;
2773 ALOGV("%s", __func__);
2774 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002775 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002776 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2777 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2778 else
2779 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2780 pthread_mutex_unlock(&out->lock);
2781 }
2782 return status;
2783}
2784
2785static int out_flush(struct audio_stream_out* stream)
2786{
2787 struct stream_out *out = (struct stream_out *)stream;
2788 ALOGV("%s", __func__);
2789 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002790 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002791 stop_compressed_output_l(out);
2792 pthread_mutex_unlock(&out->lock);
2793 return 0;
2794 }
2795 return -ENOSYS;
2796}
2797
Eric Laurent0e46adf2016-12-16 12:49:24 -08002798static int out_stop(const struct audio_stream_out* stream)
2799{
2800 struct stream_out *out = (struct stream_out *)stream;
2801 struct audio_device *adev = out->dev;
2802 int ret = -ENOSYS;
2803
2804 ALOGV("%s", __func__);
2805 pthread_mutex_lock(&adev->lock);
2806 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2807 out->playback_started && out->pcm != NULL) {
2808 pcm_stop(out->pcm);
2809 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002810 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002811 }
2812 pthread_mutex_unlock(&adev->lock);
2813 return ret;
2814}
2815
2816static int out_start(const struct audio_stream_out* stream)
2817{
2818 struct stream_out *out = (struct stream_out *)stream;
2819 struct audio_device *adev = out->dev;
2820 int ret = -ENOSYS;
2821
2822 ALOGV("%s", __func__);
2823 pthread_mutex_lock(&adev->lock);
2824 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2825 !out->playback_started && out->pcm != NULL) {
2826 ret = start_output_stream(out);
2827 if (ret == 0) {
2828 out->playback_started = true;
2829 }
2830 }
2831 pthread_mutex_unlock(&adev->lock);
2832 return ret;
2833}
2834
Phil Burkbc991042017-02-24 08:06:44 -08002835/*
2836 * Modify config->period_count based on min_size_frames
2837 */
2838static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2839{
2840 int periodCountRequested = (min_size_frames + config->period_size - 1)
2841 / config->period_size;
2842 int periodCount = MMAP_PERIOD_COUNT_MIN;
2843
2844 ALOGV("%s original config.period_size = %d config.period_count = %d",
2845 __func__, config->period_size, config->period_count);
2846
2847 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2848 periodCount *= 2;
2849 }
2850 config->period_count = periodCount;
2851
2852 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2853}
2854
Eric Laurent0e46adf2016-12-16 12:49:24 -08002855static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2856 int32_t min_size_frames,
2857 struct audio_mmap_buffer_info *info)
2858{
2859 struct stream_out *out = (struct stream_out *)stream;
2860 struct audio_device *adev = out->dev;
2861 int ret = 0;
2862 unsigned int offset1;
2863 unsigned int frames1;
2864 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002865 uint32_t mmap_size;
2866 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002867
2868 ALOGV("%s", __func__);
2869 pthread_mutex_lock(&adev->lock);
2870
2871 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002872 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002873 ret = -EINVAL;
2874 goto exit;
2875 }
2876 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002877 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002878 ret = -ENOSYS;
2879 goto exit;
2880 }
2881 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2882 if (out->pcm_device_id < 0) {
2883 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2884 __func__, out->pcm_device_id, out->usecase);
2885 ret = -EINVAL;
2886 goto exit;
2887 }
Phil Burkbc991042017-02-24 08:06:44 -08002888
2889 adjust_mmap_period_count(&out->config, min_size_frames);
2890
Eric Laurent0e46adf2016-12-16 12:49:24 -08002891 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2892 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2893 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2894 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2895 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2896 step = "open";
2897 ret = -ENODEV;
2898 goto exit;
2899 }
2900 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2901 if (ret < 0) {
2902 step = "begin";
2903 goto exit;
2904 }
2905 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002906 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002907 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002908 ret = platform_get_mmap_data_fd(adev->platform,
2909 out->pcm_device_id, 0 /*playback*/,
2910 &info->shared_memory_fd,
2911 &mmap_size);
2912 if (ret < 0) {
2913 // Fall back to non exclusive mode
2914 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2915 } else {
2916 if (mmap_size < buffer_size) {
2917 step = "mmap";
2918 goto exit;
2919 }
2920 // FIXME: indicate exclusive mode support by returning a negative buffer size
2921 info->buffer_size_frames *= -1;
2922 }
2923 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002924
2925 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2926 if (ret < 0) {
2927 step = "commit";
2928 goto exit;
2929 }
Phil Burkbc991042017-02-24 08:06:44 -08002930
2931 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002932 ret = 0;
2933
2934 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2935 __func__, info->shared_memory_address, info->buffer_size_frames);
2936
2937exit:
2938 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002939 if (out->pcm == NULL) {
2940 ALOGE("%s: %s - %d", __func__, step, ret);
2941 } else {
2942 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002943 pcm_close(out->pcm);
2944 out->pcm = NULL;
2945 }
2946 }
2947 pthread_mutex_unlock(&adev->lock);
2948 return ret;
2949}
2950
2951static int out_get_mmap_position(const struct audio_stream_out *stream,
2952 struct audio_mmap_position *position)
2953{
2954 struct stream_out *out = (struct stream_out *)stream;
2955 ALOGVV("%s", __func__);
2956 if (position == NULL) {
2957 return -EINVAL;
2958 }
2959 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2960 return -ENOSYS;
2961 }
2962 if (out->pcm == NULL) {
2963 return -ENOSYS;
2964 }
2965
2966 struct timespec ts = { 0, 0 };
2967 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2968 if (ret < 0) {
2969 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2970 return ret;
2971 }
Andy Hungfc044e12017-03-20 09:24:22 -07002972 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002973 return 0;
2974}
2975
2976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002977/** audio_stream_in implementation **/
2978static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2979{
2980 struct stream_in *in = (struct stream_in *)stream;
2981
2982 return in->config.rate;
2983}
2984
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002985static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986{
2987 return -ENOSYS;
2988}
2989
2990static size_t in_get_buffer_size(const struct audio_stream *stream)
2991{
2992 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002993 return in->config.period_size * in->af_period_multiplier *
2994 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002995}
2996
2997static uint32_t in_get_channels(const struct audio_stream *stream)
2998{
2999 struct stream_in *in = (struct stream_in *)stream;
3000
3001 return in->channel_mask;
3002}
3003
vivek mehta4ed66e62016-04-15 23:33:34 -07003004static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005{
vivek mehta4ed66e62016-04-15 23:33:34 -07003006 struct stream_in *in = (struct stream_in *)stream;
3007 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008}
3009
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003010static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003011{
3012 return -ENOSYS;
3013}
3014
3015static int in_standby(struct audio_stream *stream)
3016{
3017 struct stream_in *in = (struct stream_in *)stream;
3018 struct audio_device *adev = in->dev;
3019 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003020 bool do_stop = true;
3021
Eric Laurent994a6932013-07-17 11:51:42 -07003022 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003023
3024 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003025
3026 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003027 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003028 audio_extn_sound_trigger_stop_lab(in);
3029 in->standby = true;
3030 }
3031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003033 if (adev->adm_deregister_stream)
3034 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3035
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003036 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003038 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003039 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003040 in->capture_started = false;
3041 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003042 if (in->pcm) {
3043 pcm_close(in->pcm);
3044 in->pcm = NULL;
3045 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003046 adev->enable_voicerx = false;
3047 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003048 if (do_stop) {
3049 status = stop_input_stream(in);
3050 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003051 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 }
3053 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003054 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055 return status;
3056}
3057
Andy Hungd13f0d32017-06-12 13:58:37 -07003058static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059{
Andy Hungd13f0d32017-06-12 13:58:37 -07003060 struct stream_in *in = (struct stream_in *)stream;
3061
3062 // We try to get the lock for consistency,
3063 // but it isn't necessary for these variables.
3064 // If we're not in standby, we may be blocked on a read.
3065 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3066 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3067 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3068 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3069
3070 if (locked) {
3071 pthread_mutex_unlock(&in->lock);
3072 }
3073
3074 // dump error info
3075 (void)error_log_dump(
3076 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077 return 0;
3078}
3079
3080static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3081{
3082 struct stream_in *in = (struct stream_in *)stream;
3083 struct audio_device *adev = in->dev;
3084 struct str_parms *parms;
3085 char *str;
3086 char value[32];
3087 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003088 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089
Eric Laurent994a6932013-07-17 11:51:42 -07003090 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091 parms = str_parms_create_str(kvpairs);
3092
3093 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3094
Eric Laurenta1478072015-09-21 17:21:52 -07003095 lock_input_stream(in);
3096
Eric Laurent150dbfe2013-02-27 14:31:02 -08003097 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 if (ret >= 0) {
3099 val = atoi(value);
3100 /* no audio source uses val == 0 */
3101 if ((in->source != val) && (val != 0)) {
3102 in->source = val;
3103 }
3104 }
3105
3106 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003107
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108 if (ret >= 0) {
3109 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003110 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111 in->device = val;
3112 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003113 if (!in->standby) {
3114 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003115 // inform adm before actual routing to prevent glitches.
3116 if (adev->adm_on_routing_change) {
3117 adev->adm_on_routing_change(adev->adm_data,
3118 in->capture_handle);
3119 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003120 select_devices(adev, in->usecase);
3121 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122 }
3123 }
3124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003126 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127
3128 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003129 ALOGV("%s: exit: status(%d)", __func__, status);
3130 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131}
3132
Haynes Mathew George569b7482017-05-08 14:44:27 -07003133static char* in_get_parameters(const struct audio_stream *stream,
3134 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003135{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003136 struct stream_in *in = (struct stream_in *)stream;
3137 struct str_parms *query = str_parms_create_str(keys);
3138 char *str;
3139 struct str_parms *reply = str_parms_create();
3140 bool replied = false;
3141
3142 ALOGV("%s: enter: keys - %s", __func__, keys);
3143 replied |= stream_get_parameter_channels(query, reply,
3144 &in->supported_channel_masks[0]);
3145 replied |= stream_get_parameter_formats(query, reply,
3146 &in->supported_formats[0]);
3147 replied |= stream_get_parameter_rates(query, reply,
3148 &in->supported_sample_rates[0]);
3149 if (replied) {
3150 str = str_parms_to_str(reply);
3151 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003152 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003153 }
3154 str_parms_destroy(query);
3155 str_parms_destroy(reply);
3156 ALOGV("%s: exit: returns - %s", __func__, str);
3157 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003158}
3159
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003160static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003161{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003162 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163}
3164
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003165static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3166{
3167 if (!stream || !parms)
3168 return;
3169
3170 struct stream_in *in = (struct stream_in *)stream;
3171 struct audio_device *adev = in->dev;
3172
3173 card_status_t status;
3174 int card;
3175 if (parse_snd_card_status(parms, &card, &status) < 0)
3176 return;
3177
3178 pthread_mutex_lock(&adev->lock);
3179 bool valid_cb = (card == adev->snd_card);
3180 pthread_mutex_unlock(&adev->lock);
3181
3182 if (!valid_cb)
3183 return;
3184
3185 lock_input_stream(in);
3186 if (in->card_status != status)
3187 in->card_status = status;
3188 pthread_mutex_unlock(&in->lock);
3189
3190 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3191 use_case_table[in->usecase],
3192 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3193
3194 // a better solution would be to report error back to AF and let
3195 // it put the stream to standby
3196 if (status == CARD_STATUS_OFFLINE)
3197 in_standby(&in->stream.common);
3198
3199 return;
3200}
3201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3203 size_t bytes)
3204{
3205 struct stream_in *in = (struct stream_in *)stream;
3206 struct audio_device *adev = in->dev;
3207 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003208 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003209 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210
Eric Laurenta1478072015-09-21 17:21:52 -07003211 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003212 const size_t frame_size = audio_stream_in_frame_size(stream);
3213 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003214
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003215 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003216 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003217 /* Read from sound trigger HAL */
3218 audio_extn_sound_trigger_read(in, buffer, bytes);
3219 pthread_mutex_unlock(&in->lock);
3220 return bytes;
3221 }
3222
Eric Laurent0e46adf2016-12-16 12:49:24 -08003223 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3224 ret = -ENOSYS;
3225 goto exit;
3226 }
3227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003229 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003231 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 goto exit;
3234 }
3235 in->standby = 0;
3236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003237
Andy Hungd13f0d32017-06-12 13:58:37 -07003238 // errors that occur here are read errors.
3239 error_code = ERROR_CODE_READ;
3240
Haynes Mathew George03c40102016-01-29 17:57:48 -08003241 //what's the duration requested by the client?
3242 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3243 in->config.rate;
3244 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003245
Haynes Mathew George03c40102016-01-29 17:57:48 -08003246 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003248 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003249 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003250 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003251 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003252 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003253 if (ret < 0) {
3254 ALOGE("Failed to read w/err %s", strerror(errno));
3255 ret = -errno;
3256 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003257 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3258 if (bytes % 4 == 0) {
3259 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3260 int_buf_stream = buffer;
3261 for (size_t itt=0; itt < bytes/4 ; itt++) {
3262 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003263 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003264 } else {
3265 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3266 ret = -EINVAL;
3267 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003268 }
3269 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270 }
3271
Haynes Mathew George03c40102016-01-29 17:57:48 -08003272 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003273
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274 /*
3275 * Instead of writing zeroes here, we could trust the hardware
3276 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003277 * 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 -08003278 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003279 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003281 in->frames_muted += frames;
3282 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283
3284exit:
3285 pthread_mutex_unlock(&in->lock);
3286
3287 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003288 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289 in_standby(&in->stream.common);
3290 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003291 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003292 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003293 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003294 }
3295 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003296 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003297 }
3298 return bytes;
3299}
3300
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003301static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003302{
3303 return 0;
3304}
3305
Andy Hung6ebe5962016-01-15 17:46:57 -08003306static int in_get_capture_position(const struct audio_stream_in *stream,
3307 int64_t *frames, int64_t *time)
3308{
3309 if (stream == NULL || frames == NULL || time == NULL) {
3310 return -EINVAL;
3311 }
3312 struct stream_in *in = (struct stream_in *)stream;
3313 int ret = -ENOSYS;
3314
3315 lock_input_stream(in);
3316 if (in->pcm) {
3317 struct timespec timestamp;
3318 unsigned int avail;
3319 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3320 *frames = in->frames_read + avail;
3321 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3322 ret = 0;
3323 }
3324 }
3325 pthread_mutex_unlock(&in->lock);
3326 return ret;
3327}
3328
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003329static int add_remove_audio_effect(const struct audio_stream *stream,
3330 effect_handle_t effect,
3331 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003332{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003333 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003334 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003335 int status = 0;
3336 effect_descriptor_t desc;
3337
3338 status = (*effect)->get_descriptor(effect, &desc);
3339 if (status != 0)
3340 return status;
3341
Eric Laurenta1478072015-09-21 17:21:52 -07003342 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003343 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003344 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003345 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003346 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003347 in->enable_aec != enable &&
3348 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3349 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003350 if (!enable)
3351 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003352 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3353 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3354 adev->enable_voicerx = enable;
3355 struct audio_usecase *usecase;
3356 struct listnode *node;
3357 list_for_each(node, &adev->usecase_list) {
3358 usecase = node_to_item(node, struct audio_usecase, list);
3359 if (usecase->type == PCM_PLAYBACK) {
3360 select_devices(adev, usecase->id);
3361 break;
3362 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003363 }
3364 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003365 if (!in->standby)
3366 select_devices(in->dev, in->usecase);
3367 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003368 if (in->enable_ns != enable &&
3369 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3370 in->enable_ns = enable;
3371 if (!in->standby)
3372 select_devices(in->dev, in->usecase);
3373 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003374 pthread_mutex_unlock(&in->dev->lock);
3375 pthread_mutex_unlock(&in->lock);
3376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 return 0;
3378}
3379
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003380static int in_add_audio_effect(const struct audio_stream *stream,
3381 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382{
Eric Laurent994a6932013-07-17 11:51:42 -07003383 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003384 return add_remove_audio_effect(stream, effect, true);
3385}
3386
3387static int in_remove_audio_effect(const struct audio_stream *stream,
3388 effect_handle_t effect)
3389{
Eric Laurent994a6932013-07-17 11:51:42 -07003390 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003391 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392}
3393
Eric Laurent0e46adf2016-12-16 12:49:24 -08003394static int in_stop(const struct audio_stream_in* stream)
3395{
3396 struct stream_in *in = (struct stream_in *)stream;
3397 struct audio_device *adev = in->dev;
3398
3399 int ret = -ENOSYS;
3400 ALOGV("%s", __func__);
3401 pthread_mutex_lock(&adev->lock);
3402 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3403 in->capture_started && in->pcm != NULL) {
3404 pcm_stop(in->pcm);
3405 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003406 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003407 }
3408 pthread_mutex_unlock(&adev->lock);
3409 return ret;
3410}
3411
3412static int in_start(const struct audio_stream_in* stream)
3413{
3414 struct stream_in *in = (struct stream_in *)stream;
3415 struct audio_device *adev = in->dev;
3416 int ret = -ENOSYS;
3417
3418 ALOGV("%s in %p", __func__, in);
3419 pthread_mutex_lock(&adev->lock);
3420 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3421 !in->capture_started && in->pcm != NULL) {
3422 if (!in->capture_started) {
3423 ret = start_input_stream(in);
3424 if (ret == 0) {
3425 in->capture_started = true;
3426 }
3427 }
3428 }
3429 pthread_mutex_unlock(&adev->lock);
3430 return ret;
3431}
3432
3433static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3434 int32_t min_size_frames,
3435 struct audio_mmap_buffer_info *info)
3436{
3437 struct stream_in *in = (struct stream_in *)stream;
3438 struct audio_device *adev = in->dev;
3439 int ret = 0;
3440 unsigned int offset1;
3441 unsigned int frames1;
3442 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003443 uint32_t mmap_size;
3444 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003445
3446 pthread_mutex_lock(&adev->lock);
3447 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003448
Eric Laurent0e46adf2016-12-16 12:49:24 -08003449 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003450 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003451 ret = -EINVAL;
3452 goto exit;
3453 }
3454 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003455 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003456 ALOGV("%s in %p", __func__, in);
3457 ret = -ENOSYS;
3458 goto exit;
3459 }
3460 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3461 if (in->pcm_device_id < 0) {
3462 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3463 __func__, in->pcm_device_id, in->usecase);
3464 ret = -EINVAL;
3465 goto exit;
3466 }
Phil Burkbc991042017-02-24 08:06:44 -08003467
3468 adjust_mmap_period_count(&in->config, min_size_frames);
3469
Eric Laurent0e46adf2016-12-16 12:49:24 -08003470 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3471 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3472 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3473 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3474 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3475 step = "open";
3476 ret = -ENODEV;
3477 goto exit;
3478 }
3479
3480 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3481 if (ret < 0) {
3482 step = "begin";
3483 goto exit;
3484 }
3485 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003486 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003487 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003488 ret = platform_get_mmap_data_fd(adev->platform,
3489 in->pcm_device_id, 1 /*capture*/,
3490 &info->shared_memory_fd,
3491 &mmap_size);
3492 if (ret < 0) {
3493 // Fall back to non exclusive mode
3494 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3495 } else {
3496 if (mmap_size < buffer_size) {
3497 step = "mmap";
3498 goto exit;
3499 }
3500 // FIXME: indicate exclusive mode support by returning a negative buffer size
3501 info->buffer_size_frames *= -1;
3502 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003503
Haynes Mathew George96483a22017-03-28 14:52:47 -07003504 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003505
3506 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3507 if (ret < 0) {
3508 step = "commit";
3509 goto exit;
3510 }
3511
Phil Burkbc991042017-02-24 08:06:44 -08003512 in->standby = false;
3513 ret = 0;
3514
Eric Laurent0e46adf2016-12-16 12:49:24 -08003515 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3516 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003517
3518exit:
3519 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003520 if (in->pcm == NULL) {
3521 ALOGE("%s: %s - %d", __func__, step, ret);
3522 } else {
3523 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003524 pcm_close(in->pcm);
3525 in->pcm = NULL;
3526 }
3527 }
3528 pthread_mutex_unlock(&adev->lock);
3529 return ret;
3530}
3531
3532static int in_get_mmap_position(const struct audio_stream_in *stream,
3533 struct audio_mmap_position *position)
3534{
3535 struct stream_in *in = (struct stream_in *)stream;
3536 ALOGVV("%s", __func__);
3537 if (position == NULL) {
3538 return -EINVAL;
3539 }
3540 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3541 return -ENOSYS;
3542 }
3543 if (in->pcm == NULL) {
3544 return -ENOSYS;
3545 }
3546 struct timespec ts = { 0, 0 };
3547 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3548 if (ret < 0) {
3549 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3550 return ret;
3551 }
Andy Hungfc044e12017-03-20 09:24:22 -07003552 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003553 return 0;
3554}
3555
3556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557static int adev_open_output_stream(struct audio_hw_device *dev,
3558 audio_io_handle_t handle,
3559 audio_devices_t devices,
3560 audio_output_flags_t flags,
3561 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003562 struct audio_stream_out **stream_out,
3563 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564{
3565 struct audio_device *adev = (struct audio_device *)dev;
3566 struct stream_out *out;
3567 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003568 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3569 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3570 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3571 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572
Eric Laurent994a6932013-07-17 11:51:42 -07003573 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 __func__, config->sample_rate, config->channel_mask, devices, flags);
3575 *stream_out = NULL;
3576 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3577
3578 if (devices == AUDIO_DEVICE_NONE)
3579 devices = AUDIO_DEVICE_OUT_SPEAKER;
3580
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 out->flags = flags;
3582 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003583 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003584 out->format = config->format;
3585 out->sample_rate = config->sample_rate;
3586 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3587 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003588 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589
3590 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003591 if (audio_is_linear_pcm(out->format) &&
3592 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003593 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003594 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003595 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003596 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003597 if (config->sample_rate == 0)
3598 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3599 if (config->channel_mask == 0)
3600 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3601 if (config->format == AUDIO_FORMAT_DEFAULT)
3602 config->format = AUDIO_FORMAT_PCM_16_BIT;
3603 } else if (is_usb_dev) {
3604 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3605 &config->format,
3606 &out->supported_formats[0],
3607 MAX_SUPPORTED_FORMATS,
3608 &config->channel_mask,
3609 &out->supported_channel_masks[0],
3610 MAX_SUPPORTED_CHANNEL_MASKS,
3611 &config->sample_rate,
3612 &out->supported_sample_rates[0],
3613 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003614 ALOGV("plugged dev USB ret %d", ret);
3615 } else {
3616 ret = -1;
3617 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003618 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003619 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003620 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003621
Haynes Mathew George569b7482017-05-08 14:44:27 -07003622 out->channel_mask = config->channel_mask;
3623 out->sample_rate = config->sample_rate;
3624 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003625 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3626 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003627 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003628 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003629 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Andy Hung928efbe2017-06-12 14:05:22 -07003630 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3631 audio_bytes_per_sample(config->format));
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003632 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003633 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003634 pthread_mutex_lock(&adev->lock);
3635 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3636 pthread_mutex_unlock(&adev->lock);
3637
3638 // reject offload during card offline to allow
3639 // fallback to s/w paths
3640 if (offline) {
3641 ret = -ENODEV;
3642 goto error_open;
3643 }
3644
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003645 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3646 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3647 ALOGE("%s: Unsupported Offload information", __func__);
3648 ret = -EINVAL;
3649 goto error_open;
3650 }
3651 if (!is_supported_format(config->offload_info.format)) {
3652 ALOGE("%s: Unsupported audio format", __func__);
3653 ret = -EINVAL;
3654 goto error_open;
3655 }
3656
3657 out->compr_config.codec = (struct snd_codec *)
3658 calloc(1, sizeof(struct snd_codec));
3659
3660 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3661 if (config->offload_info.channel_mask)
3662 out->channel_mask = config->offload_info.channel_mask;
3663 else if (config->channel_mask)
3664 out->channel_mask = config->channel_mask;
3665 out->format = config->offload_info.format;
3666 out->sample_rate = config->offload_info.sample_rate;
3667
3668 out->stream.set_callback = out_set_callback;
3669 out->stream.pause = out_pause;
3670 out->stream.resume = out_resume;
3671 out->stream.drain = out_drain;
3672 out->stream.flush = out_flush;
3673
3674 out->compr_config.codec->id =
3675 get_snd_codec_id(config->offload_info.format);
3676 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3677 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003678 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003679 out->compr_config.codec->bit_rate =
3680 config->offload_info.bit_rate;
3681 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003682 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003683 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3684
3685 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3686 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003687
3688 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003689 create_offload_callback_thread(out);
3690 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3691 __func__, config->offload_info.version,
3692 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003693 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003694 switch (config->sample_rate) {
3695 case 8000:
3696 case 16000:
3697 case 48000:
3698 out->sample_rate = config->sample_rate;
3699 break;
3700 default:
3701 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003702 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003703 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003704 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3705 out->config = pcm_config_afe_proxy_playback;
3706 adev->voice_tx_output = out;
David Lin6b00c232017-07-26 00:20:16 -07003707 } else if (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3708 AUDIO_OUTPUT_FLAG_VOIP_RX)) {
vivek mehtaa68fea62017-06-08 19:04:02 -07003709 uint32_t buffer_size, frame_size;
3710 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3711 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3712 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3713 out->config = pcm_config_voip;
3714 out->config.format = pcm_format_from_audio_format(config->format);
3715 out->config.rate = config->sample_rate;
3716 out->config.channels =
3717 audio_channel_count_from_out_mask(config->channel_mask);
3718 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3719 config->sample_rate,
3720 config->format,
3721 out->config.channels,
3722 false /*is_low_latency*/);
3723 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3724 out->config.period_size = buffer_size / frame_size;
3725 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3726 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003728 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3729 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3730 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003731 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3732 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3733 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003734 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3735 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003736 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003737 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003738 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3739 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3740 out->config = pcm_config_mmap_playback;
3741 out->stream.start = out_start;
3742 out->stream.stop = out_stop;
3743 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3744 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003745 } else {
3746 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3747 out->config = pcm_config_low_latency;
3748 }
3749 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003750 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003751 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003752 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003754
3755 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3756 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3757 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3758 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3759 __func__, config->sample_rate, config->format, config->channel_mask);
3760 config->sample_rate = out->sample_rate;
3761 config->format = out->format;
3762 config->channel_mask = out->channel_mask;
3763 ret = -EINVAL;
3764 goto error_open;
3765 }
3766
Andy Hung6fcba9c2014-03-18 11:53:32 -07003767 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3768 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003770 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003771 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003772 adev->primary_output = out;
3773 else {
3774 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003775 ret = -EEXIST;
3776 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003777 }
3778 }
3779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 /* Check if this usecase is already existing */
3781 pthread_mutex_lock(&adev->lock);
3782 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3783 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003785 ret = -EEXIST;
3786 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 }
3788 pthread_mutex_unlock(&adev->lock);
3789
3790 out->stream.common.get_sample_rate = out_get_sample_rate;
3791 out->stream.common.set_sample_rate = out_set_sample_rate;
3792 out->stream.common.get_buffer_size = out_get_buffer_size;
3793 out->stream.common.get_channels = out_get_channels;
3794 out->stream.common.get_format = out_get_format;
3795 out->stream.common.set_format = out_set_format;
3796 out->stream.common.standby = out_standby;
3797 out->stream.common.dump = out_dump;
3798 out->stream.common.set_parameters = out_set_parameters;
3799 out->stream.common.get_parameters = out_get_parameters;
3800 out->stream.common.add_audio_effect = out_add_audio_effect;
3801 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3802 out->stream.get_latency = out_get_latency;
3803 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003804#ifdef NO_AUDIO_OUT
3805 out->stream.write = out_write_for_no_output;
3806#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003807 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003808#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809 out->stream.get_render_position = out_get_render_position;
3810 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003811 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812
Eric Laurent0e46adf2016-12-16 12:49:24 -08003813 if (out->realtime)
3814 out->af_period_multiplier = af_period_multiplier;
3815 else
3816 out->af_period_multiplier = 1;
3817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003819 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003820 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003822 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003823 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003824 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3825
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826 config->format = out->stream.common.get_format(&out->stream.common);
3827 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3828 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3829
Andy Hunga452b0a2017-03-15 14:51:15 -07003830 out->error_log = error_log_create(
3831 ERROR_LOG_ENTRIES,
3832 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3833
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003834 /*
3835 By locking output stream before registering, we allow the callback
3836 to update stream's state only after stream's initial state is set to
3837 adev state.
3838 */
3839 lock_output_stream(out);
3840 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3841 pthread_mutex_lock(&adev->lock);
3842 out->card_status = adev->card_status;
3843 pthread_mutex_unlock(&adev->lock);
3844 pthread_mutex_unlock(&out->lock);
3845
vivek mehta4a824772017-06-08 19:05:49 -07003846 stream_app_type_cfg_init(&out->app_type_cfg);
3847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003849
Eric Laurent994a6932013-07-17 11:51:42 -07003850 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003852
3853error_open:
3854 free(out);
3855 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003856 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003857 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858}
3859
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003860static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861 struct audio_stream_out *stream)
3862{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003863 struct stream_out *out = (struct stream_out *)stream;
3864 struct audio_device *adev = out->dev;
3865
Eric Laurent994a6932013-07-17 11:51:42 -07003866 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003867
3868 // must deregister from sndmonitor first to prevent races
3869 // between the callback and close_stream
3870 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003872 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3873 destroy_offload_callback_thread(out);
3874
3875 if (out->compr_config.codec != NULL)
3876 free(out->compr_config.codec);
3877 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003878
3879 if (adev->voice_tx_output == out)
3880 adev->voice_tx_output = NULL;
3881
Andy Hunga452b0a2017-03-15 14:51:15 -07003882 error_log_destroy(out->error_log);
3883 out->error_log = NULL;
3884
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003885 pthread_cond_destroy(&out->cond);
3886 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003888 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889}
3890
3891static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3892{
3893 struct audio_device *adev = (struct audio_device *)dev;
3894 struct str_parms *parms;
3895 char *str;
3896 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003897 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003899 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900
Joe Onorato188b6222016-03-01 11:02:27 -08003901 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003902
3903 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904
3905 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003906 status = voice_set_parameters(adev, parms);
3907 if (status != 0) {
3908 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003909 }
3910
3911 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3912 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003913 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3915 adev->bluetooth_nrec = true;
3916 else
3917 adev->bluetooth_nrec = false;
3918 }
3919
3920 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3921 if (ret >= 0) {
3922 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3923 adev->screen_off = false;
3924 else
3925 adev->screen_off = true;
3926 }
3927
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003928 ret = str_parms_get_int(parms, "rotation", &val);
3929 if (ret >= 0) {
3930 bool reverse_speakers = false;
3931 switch(val) {
3932 // FIXME: note that the code below assumes that the speakers are in the correct placement
3933 // relative to the user when the device is rotated 90deg from its default rotation. This
3934 // assumption is device-specific, not platform-specific like this code.
3935 case 270:
3936 reverse_speakers = true;
3937 break;
3938 case 0:
3939 case 90:
3940 case 180:
3941 break;
3942 default:
3943 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003944 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003945 }
Eric Laurent03f09432014-03-25 18:09:11 -07003946 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07003947 // check and set swap
3948 // - check if orientation changed and speaker active
3949 // - set rotation and cache the rotation value
3950 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003951 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003952 }
3953
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003954 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3955 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003956 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003957 }
3958
David Linee3fe402017-03-13 10:00:42 -07003959 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3960 if (ret >= 0) {
3961 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003962 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003963 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3964 if (ret >= 0) {
3965 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003966 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003967 }
Eric Laurent99dab492017-06-17 15:19:08 -07003968 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003969 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3970 if (ret >= 0) {
3971 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003972 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003973 }
3974 }
3975 }
3976
3977 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3978 if (ret >= 0) {
3979 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003980 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003981 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3982 if (ret >= 0) {
3983 const int card = atoi(value);
3984
Eric Laurent99dab492017-06-17 15:19:08 -07003985 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003986 }
Eric Laurent99dab492017-06-17 15:19:08 -07003987 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003988 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3989 if (ret >= 0) {
3990 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003991 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003992 }
3993 }
3994 }
3995
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003996 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003997done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003999 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004000 ALOGV("%s: exit with code(%d)", __func__, status);
4001 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004002}
4003
4004static char* adev_get_parameters(const struct audio_hw_device *dev,
4005 const char *keys)
4006{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004007 struct audio_device *adev = (struct audio_device *)dev;
4008 struct str_parms *reply = str_parms_create();
4009 struct str_parms *query = str_parms_create_str(keys);
4010 char *str;
4011
4012 pthread_mutex_lock(&adev->lock);
4013
4014 voice_get_parameters(adev, query, reply);
4015 str = str_parms_to_str(reply);
4016 str_parms_destroy(query);
4017 str_parms_destroy(reply);
4018
4019 pthread_mutex_unlock(&adev->lock);
4020 ALOGV("%s: exit: returns - %s", __func__, str);
4021 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022}
4023
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004024static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004025{
4026 return 0;
4027}
4028
Haynes Mathew George5191a852013-09-11 14:19:36 -07004029static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4030{
4031 int ret;
4032 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004033
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004034 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4035
Haynes Mathew George5191a852013-09-11 14:19:36 -07004036 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004037 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004038 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004039
Haynes Mathew George5191a852013-09-11 14:19:36 -07004040 return ret;
4041}
4042
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004043static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004044{
4045 return -ENOSYS;
4046}
4047
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004048static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4049 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004050{
4051 return -ENOSYS;
4052}
4053
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004054static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055{
4056 return -ENOSYS;
4057}
4058
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004059static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060{
4061 return -ENOSYS;
4062}
4063
4064static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4065{
4066 struct audio_device *adev = (struct audio_device *)dev;
4067
4068 pthread_mutex_lock(&adev->lock);
4069 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004070 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004072 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4073 voice_is_in_call(adev)) {
4074 voice_stop_call(adev);
4075 adev->current_call_output = NULL;
4076 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004077 }
4078 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004079
4080 audio_extn_extspk_set_mode(adev->extspk, mode);
4081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004082 return 0;
4083}
4084
4085static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4086{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004087 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004088 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089
Eric Laurent2bafff12016-03-17 12:17:23 -07004090 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004091 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004092 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4093 ret = audio_extn_hfp_set_mic_mute(adev, state);
4094 } else {
4095 ret = voice_set_mic_mute(adev, state);
4096 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004097 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004098 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004099
4100 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101}
4102
4103static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4104{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004105 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106 return 0;
4107}
4108
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004109static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110 const struct audio_config *config)
4111{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004112 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004113
Eric Laurent74b55762017-07-09 17:04:53 -07004114 /* Don't know if USB HIFI in this context so use true to be conservative */
4115 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4116 true /*is_usb_hifi */) != 0)
4117 return 0;
4118
vivek mehtaa68fea62017-06-08 19:04:02 -07004119 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4120 config->sample_rate, config->format,
4121 channel_count,
4122 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123}
4124
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004125static bool adev_input_allow_hifi_record(struct audio_device *adev,
4126 audio_devices_t devices,
4127 audio_input_flags_t flags,
4128 audio_source_t source) {
4129 const bool allowed = true;
4130
4131 if (!audio_is_usb_in_device(devices))
4132 return !allowed;
4133
4134 switch (flags) {
4135 case AUDIO_INPUT_FLAG_NONE:
4136 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4137 break;
4138 default:
4139 return !allowed;
4140 }
4141
4142 switch (source) {
4143 case AUDIO_SOURCE_DEFAULT:
4144 case AUDIO_SOURCE_MIC:
4145 case AUDIO_SOURCE_UNPROCESSED:
4146 break;
4147 default:
4148 return !allowed;
4149 }
4150
4151 switch (adev->mode) {
4152 case 0:
4153 break;
4154 default:
4155 return !allowed;
4156 }
4157
4158 return allowed;
4159}
4160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004162 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004163 audio_devices_t devices,
4164 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004165 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004166 audio_input_flags_t flags,
4167 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004168 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169{
4170 struct audio_device *adev = (struct audio_device *)dev;
4171 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004172 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004173 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004174 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004175 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004176 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4177 devices,
4178 flags,
4179 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004180 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004182
Eric Laurent74b55762017-07-09 17:04:53 -07004183 if (!(is_usb_dev && may_use_hifi_record)) {
4184 if (config->sample_rate == 0)
4185 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4186 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4187 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4188 if (config->format == AUDIO_FORMAT_DEFAULT)
4189 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004190
Eric Laurent74b55762017-07-09 17:04:53 -07004191 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4192
4193 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4194 return -EINVAL;
4195 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004197 if (audio_extn_tfa_98xx_is_supported() &&
4198 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004199 return -EINVAL;
4200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4202
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004203 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004204 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004206 in->stream.common.get_sample_rate = in_get_sample_rate;
4207 in->stream.common.set_sample_rate = in_set_sample_rate;
4208 in->stream.common.get_buffer_size = in_get_buffer_size;
4209 in->stream.common.get_channels = in_get_channels;
4210 in->stream.common.get_format = in_get_format;
4211 in->stream.common.set_format = in_set_format;
4212 in->stream.common.standby = in_standby;
4213 in->stream.common.dump = in_dump;
4214 in->stream.common.set_parameters = in_set_parameters;
4215 in->stream.common.get_parameters = in_get_parameters;
4216 in->stream.common.add_audio_effect = in_add_audio_effect;
4217 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4218 in->stream.set_gain = in_set_gain;
4219 in->stream.read = in_read;
4220 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004221 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222
4223 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004224 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004225 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004226 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004227 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004228 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229
Haynes Mathew George569b7482017-05-08 14:44:27 -07004230 if (is_usb_dev && may_use_hifi_record) {
4231 /* HiFi record selects an appropriate format, channel, rate combo
4232 depending on sink capabilities*/
4233 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4234 &config->format,
4235 &in->supported_formats[0],
4236 MAX_SUPPORTED_FORMATS,
4237 &config->channel_mask,
4238 &in->supported_channel_masks[0],
4239 MAX_SUPPORTED_CHANNEL_MASKS,
4240 &config->sample_rate,
4241 &in->supported_sample_rates[0],
4242 MAX_SUPPORTED_SAMPLE_RATES);
4243 if (ret != 0) {
4244 ret = -EINVAL;
4245 goto err_open;
4246 }
Eric Laurent74b55762017-07-09 17:04:53 -07004247 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004248 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004249 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004250 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4251 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4252 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4253 bool ret_error = false;
4254 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4255 from HAL is 8_24
4256 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4257 8_24 return error indicating supported format is 8_24
4258 *> In case of any other source requesting 24 bit or float return error
4259 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004260
vivek mehta57ff9b52016-04-28 14:13:08 -07004261 on error flinger will retry with supported format passed
4262 */
4263 if (source != AUDIO_SOURCE_UNPROCESSED) {
4264 config->format = AUDIO_FORMAT_PCM_16_BIT;
4265 ret_error = true;
4266 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4267 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4268 ret_error = true;
4269 }
4270
4271 if (ret_error) {
4272 ret = -EINVAL;
4273 goto err_open;
4274 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004275 }
4276
vivek mehta57ff9b52016-04-28 14:13:08 -07004277 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004278 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004281 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4282 if (config->sample_rate == 0)
4283 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4284 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4285 config->sample_rate != 8000) {
4286 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4287 ret = -EINVAL;
4288 goto err_open;
4289 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004290
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004291 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4292 config->format = AUDIO_FORMAT_PCM_16_BIT;
4293 ret = -EINVAL;
4294 goto err_open;
4295 }
4296
4297 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4298 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004299 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004300 } else if (is_usb_dev && may_use_hifi_record) {
4301 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4302 in->config = pcm_config_audio_capture;
4303 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004304 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4305 config->sample_rate,
4306 config->format,
4307 channel_count,
4308 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004309 in->config.period_size = buffer_size / frame_size;
4310 in->config.rate = config->sample_rate;
4311 in->af_period_multiplier = 1;
4312 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004313 } else {
4314 in->usecase = USECASE_AUDIO_RECORD;
4315 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004316 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004317 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004318#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004319 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004320#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004321 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004322 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004323 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004324 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004325 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4326 config->sample_rate,
4327 config->format,
4328 channel_count,
4329 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004330 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004331 in->config.rate = config->sample_rate;
4332 in->af_period_multiplier = 1;
4333 } else {
4334 // period size is left untouched for rt mode playback
4335 in->config = pcm_config_audio_capture_rt;
4336 in->af_period_multiplier = af_period_multiplier;
4337 }
4338 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4339 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004340 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004341 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4342 in->config = pcm_config_mmap_capture;
4343 in->stream.start = in_start;
4344 in->stream.stop = in_stop;
4345 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4346 in->stream.get_mmap_position = in_get_mmap_position;
4347 in->af_period_multiplier = 1;
4348 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004349 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004350 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004351 (config->sample_rate == 8000 ||
4352 config->sample_rate == 16000 ||
4353 config->sample_rate == 32000 ||
4354 config->sample_rate == 48000) &&
4355 channel_count == 1) {
4356 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4357 in->config = pcm_config_audio_capture;
4358 frame_size = audio_stream_in_frame_size(&in->stream);
4359 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4360 config->sample_rate,
4361 config->format,
4362 channel_count, false /*is_low_latency*/);
4363 in->config.period_size = buffer_size / frame_size;
4364 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4365 in->config.rate = config->sample_rate;
4366 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004367 } else {
4368 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004369 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004370 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4371 config->sample_rate,
4372 config->format,
4373 channel_count,
4374 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004375 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004376 in->config.rate = config->sample_rate;
4377 in->af_period_multiplier = 1;
4378 }
4379 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4380 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004381 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004382
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004384 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385
Andy Hungd13f0d32017-06-12 13:58:37 -07004386 in->error_log = error_log_create(
4387 ERROR_LOG_ENTRIES,
4388 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4389
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004390 /* This stream could be for sound trigger lab,
4391 get sound trigger pcm if present */
4392 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004394 lock_input_stream(in);
4395 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4396 pthread_mutex_lock(&adev->lock);
4397 in->card_status = adev->card_status;
4398 pthread_mutex_unlock(&adev->lock);
4399 pthread_mutex_unlock(&in->lock);
4400
vivek mehta4a824772017-06-08 19:05:49 -07004401 stream_app_type_cfg_init(&in->app_type_cfg);
4402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004404 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004405 return 0;
4406
4407err_open:
4408 free(in);
4409 *stream_in = NULL;
4410 return ret;
4411}
4412
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004413static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004414 struct audio_stream_in *stream)
4415{
Andy Hungd13f0d32017-06-12 13:58:37 -07004416 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004417 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004418
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004419 // must deregister from sndmonitor first to prevent races
4420 // between the callback and close_stream
4421 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004422 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004423
4424 error_log_destroy(in->error_log);
4425 in->error_log = NULL;
4426
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004427 free(stream);
4428
4429 return;
4430}
4431
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004432static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004433{
4434 return 0;
4435}
4436
Andy Hung31aca912014-03-20 17:14:59 -07004437/* verifies input and output devices and their capabilities.
4438 *
4439 * This verification is required when enabling extended bit-depth or
4440 * sampling rates, as not all qcom products support it.
4441 *
4442 * Suitable for calling only on initialization such as adev_open().
4443 * It fills the audio_device use_case_table[] array.
4444 *
4445 * Has a side-effect that it needs to configure audio routing / devices
4446 * in order to power up the devices and read the device parameters.
4447 * It does not acquire any hw device lock. Should restore the devices
4448 * back to "normal state" upon completion.
4449 */
4450static int adev_verify_devices(struct audio_device *adev)
4451{
4452 /* enumeration is a bit difficult because one really wants to pull
4453 * the use_case, device id, etc from the hidden pcm_device_table[].
4454 * In this case there are the following use cases and device ids.
4455 *
4456 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4457 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004458 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004459 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4460 * [USECASE_AUDIO_RECORD] = {0, 0},
4461 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4462 * [USECASE_VOICE_CALL] = {2, 2},
4463 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004464 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004465 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4466 */
4467
4468 /* should be the usecases enabled in adev_open_input_stream() */
4469 static const int test_in_usecases[] = {
4470 USECASE_AUDIO_RECORD,
4471 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4472 };
4473 /* should be the usecases enabled in adev_open_output_stream()*/
4474 static const int test_out_usecases[] = {
4475 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4476 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4477 };
4478 static const usecase_type_t usecase_type_by_dir[] = {
4479 PCM_PLAYBACK,
4480 PCM_CAPTURE,
4481 };
4482 static const unsigned flags_by_dir[] = {
4483 PCM_OUT,
4484 PCM_IN,
4485 };
4486
4487 size_t i;
4488 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004489 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004490 char info[512]; /* for possible debug info */
4491
4492 for (dir = 0; dir < 2; ++dir) {
4493 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4494 const unsigned flags_dir = flags_by_dir[dir];
4495 const size_t testsize =
4496 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4497 const int *testcases =
4498 dir ? test_in_usecases : test_out_usecases;
4499 const audio_devices_t audio_device =
4500 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4501
4502 for (i = 0; i < testsize; ++i) {
4503 const audio_usecase_t audio_usecase = testcases[i];
4504 int device_id;
4505 snd_device_t snd_device;
4506 struct pcm_params **pparams;
4507 struct stream_out out;
4508 struct stream_in in;
4509 struct audio_usecase uc_info;
4510 int retval;
4511
4512 pparams = &adev->use_case_table[audio_usecase];
4513 pcm_params_free(*pparams); /* can accept null input */
4514 *pparams = NULL;
4515
4516 /* find the device ID for the use case (signed, for error) */
4517 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4518 if (device_id < 0)
4519 continue;
4520
4521 /* prepare structures for device probing */
4522 memset(&uc_info, 0, sizeof(uc_info));
4523 uc_info.id = audio_usecase;
4524 uc_info.type = usecase_type;
4525 if (dir) {
4526 adev->active_input = &in;
4527 memset(&in, 0, sizeof(in));
4528 in.device = audio_device;
4529 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4530 uc_info.stream.in = &in;
4531 } else {
4532 adev->active_input = NULL;
4533 }
4534 memset(&out, 0, sizeof(out));
4535 out.devices = audio_device; /* only field needed in select_devices */
4536 uc_info.stream.out = &out;
4537 uc_info.devices = audio_device;
4538 uc_info.in_snd_device = SND_DEVICE_NONE;
4539 uc_info.out_snd_device = SND_DEVICE_NONE;
4540 list_add_tail(&adev->usecase_list, &uc_info.list);
4541
4542 /* select device - similar to start_(in/out)put_stream() */
4543 retval = select_devices(adev, audio_usecase);
4544 if (retval >= 0) {
4545 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4546#if LOG_NDEBUG == 0
4547 if (*pparams) {
4548 ALOGV("%s: (%s) card %d device %d", __func__,
4549 dir ? "input" : "output", card_id, device_id);
4550 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004551 } else {
4552 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4553 }
4554#endif
4555 }
4556
4557 /* deselect device - similar to stop_(in/out)put_stream() */
4558 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004559 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004560 /* 2. Disable the rx device */
4561 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004562 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004563 list_remove(&uc_info.list);
4564 }
4565 }
4566 adev->active_input = NULL; /* restore adev state */
4567 return 0;
4568}
4569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004570static int adev_close(hw_device_t *device)
4571{
Andy Hung31aca912014-03-20 17:14:59 -07004572 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004573 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004574
4575 if (!adev)
4576 return 0;
4577
4578 pthread_mutex_lock(&adev_init_lock);
4579
4580 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004581 audio_extn_snd_mon_unregister_listener(adev);
4582 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004583 audio_route_free(adev->audio_route);
4584 free(adev->snd_dev_ref_cnt);
4585 platform_deinit(adev->platform);
4586 audio_extn_extspk_deinit(adev->extspk);
4587 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004588 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004589 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4590 pcm_params_free(adev->use_case_table[i]);
4591 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004592 if (adev->adm_deinit)
4593 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004594 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004595 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004596
4597 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004599 return 0;
4600}
4601
Glenn Kasten4f993392014-05-14 07:30:48 -07004602/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4603 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4604 * just that it _might_ work.
4605 */
4606static int period_size_is_plausible_for_low_latency(int period_size)
4607{
4608 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004609 case 48:
4610 case 96:
4611 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004612 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004613 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004614 case 240:
4615 case 320:
4616 case 480:
4617 return 1;
4618 default:
4619 return 0;
4620 }
4621}
4622
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004623static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4624{
4625 int card;
4626 card_status_t status;
4627
4628 if (!parms)
4629 return;
4630
4631 if (parse_snd_card_status(parms, &card, &status) < 0)
4632 return;
4633
4634 pthread_mutex_lock(&adev->lock);
4635 bool valid_cb = (card == adev->snd_card);
4636 if (valid_cb) {
4637 if (adev->card_status != status) {
4638 adev->card_status = status;
4639 platform_snd_card_update(adev->platform, status);
4640 }
4641 }
4642 pthread_mutex_unlock(&adev->lock);
4643 return;
4644}
4645
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646static int adev_open(const hw_module_t *module, const char *name,
4647 hw_device_t **device)
4648{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004649 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650
Eric Laurent2bafff12016-03-17 12:17:23 -07004651 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004653 pthread_mutex_lock(&adev_init_lock);
4654 if (audio_device_ref_count != 0) {
4655 *device = &adev->device.common;
4656 audio_device_ref_count++;
4657 ALOGV("%s: returning existing instance of adev", __func__);
4658 ALOGV("%s: exit", __func__);
4659 pthread_mutex_unlock(&adev_init_lock);
4660 return 0;
4661 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004662 adev = calloc(1, sizeof(struct audio_device));
4663
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004664 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004666 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4667 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4668 adev->device.common.module = (struct hw_module_t *)module;
4669 adev->device.common.close = adev_close;
4670
4671 adev->device.init_check = adev_init_check;
4672 adev->device.set_voice_volume = adev_set_voice_volume;
4673 adev->device.set_master_volume = adev_set_master_volume;
4674 adev->device.get_master_volume = adev_get_master_volume;
4675 adev->device.set_master_mute = adev_set_master_mute;
4676 adev->device.get_master_mute = adev_get_master_mute;
4677 adev->device.set_mode = adev_set_mode;
4678 adev->device.set_mic_mute = adev_set_mic_mute;
4679 adev->device.get_mic_mute = adev_get_mic_mute;
4680 adev->device.set_parameters = adev_set_parameters;
4681 adev->device.get_parameters = adev_get_parameters;
4682 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4683 adev->device.open_output_stream = adev_open_output_stream;
4684 adev->device.close_output_stream = adev_close_output_stream;
4685 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004687 adev->device.close_input_stream = adev_close_input_stream;
4688 adev->device.dump = adev_dump;
4689
4690 /* Set the default route before the PCM stream is opened */
4691 pthread_mutex_lock(&adev->lock);
4692 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004693 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004694 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004695 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004696 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004697 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004698 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004699 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004700 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701 pthread_mutex_unlock(&adev->lock);
4702
4703 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004704 adev->platform = platform_init(adev);
4705 if (!adev->platform) {
4706 free(adev->snd_dev_ref_cnt);
4707 free(adev);
4708 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4709 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004710 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004711 return -EINVAL;
4712 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004713 adev->extspk = audio_extn_extspk_init(adev);
4714
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004715 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4716 if (adev->visualizer_lib == NULL) {
4717 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4718 } else {
4719 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4720 adev->visualizer_start_output =
4721 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4722 "visualizer_hal_start_output");
4723 adev->visualizer_stop_output =
4724 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4725 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004726 }
4727
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004728 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4729 if (adev->offload_effects_lib == NULL) {
4730 ALOGW("%s: DLOPEN failed for %s", __func__,
4731 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4732 } else {
4733 ALOGV("%s: DLOPEN successful for %s", __func__,
4734 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4735 adev->offload_effects_start_output =
4736 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4737 "offload_effects_bundle_hal_start_output");
4738 adev->offload_effects_stop_output =
4739 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4740 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004741 }
4742
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004743 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4744 if (adev->adm_lib == NULL) {
4745 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4746 } else {
4747 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4748 adev->adm_init = (adm_init_t)
4749 dlsym(adev->adm_lib, "adm_init");
4750 adev->adm_deinit = (adm_deinit_t)
4751 dlsym(adev->adm_lib, "adm_deinit");
4752 adev->adm_register_input_stream = (adm_register_input_stream_t)
4753 dlsym(adev->adm_lib, "adm_register_input_stream");
4754 adev->adm_register_output_stream = (adm_register_output_stream_t)
4755 dlsym(adev->adm_lib, "adm_register_output_stream");
4756 adev->adm_deregister_stream = (adm_deregister_stream_t)
4757 dlsym(adev->adm_lib, "adm_deregister_stream");
4758 adev->adm_request_focus = (adm_request_focus_t)
4759 dlsym(adev->adm_lib, "adm_request_focus");
4760 adev->adm_abandon_focus = (adm_abandon_focus_t)
4761 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004762 adev->adm_set_config = (adm_set_config_t)
4763 dlsym(adev->adm_lib, "adm_set_config");
4764 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4765 dlsym(adev->adm_lib, "adm_request_focus_v2");
4766 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4767 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4768 adev->adm_on_routing_change = (adm_on_routing_change_t)
4769 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004770 }
4771
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004772 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004773 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004775 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004776
Andy Hung31aca912014-03-20 17:14:59 -07004777 if (k_enable_extended_precision)
4778 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004779
Glenn Kasten4f993392014-05-14 07:30:48 -07004780 char value[PROPERTY_VALUE_MAX];
4781 int trial;
4782 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4783 trial = atoi(value);
4784 if (period_size_is_plausible_for_low_latency(trial)) {
4785 pcm_config_low_latency.period_size = trial;
4786 pcm_config_low_latency.start_threshold = trial / 4;
4787 pcm_config_low_latency.avail_min = trial / 4;
4788 configured_low_latency_capture_period_size = trial;
4789 }
4790 }
4791 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4792 trial = atoi(value);
4793 if (period_size_is_plausible_for_low_latency(trial)) {
4794 configured_low_latency_capture_period_size = trial;
4795 }
4796 }
4797
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004798 // commented as full set of app type cfg is sent from platform
4799 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004800 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004801
4802 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4803 af_period_multiplier = atoi(value);
4804 if (af_period_multiplier < 0) {
4805 af_period_multiplier = 2;
4806 } else if (af_period_multiplier > 4) {
4807 af_period_multiplier = 4;
4808 }
4809 ALOGV("new period_multiplier = %d", af_period_multiplier);
4810 }
4811
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004812 audio_extn_tfa_98xx_init(adev);
4813
vivek mehta1a9b7c02015-06-25 11:49:38 -07004814 pthread_mutex_unlock(&adev_init_lock);
4815
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004816 if (adev->adm_init)
4817 adev->adm_data = adev->adm_init();
4818
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004819 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004820 audio_extn_snd_mon_init();
4821 pthread_mutex_lock(&adev->lock);
4822 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4823 adev->card_status = CARD_STATUS_ONLINE;
4824 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004825 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004826
Eric Laurent2bafff12016-03-17 12:17:23 -07004827 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828 return 0;
4829}
4830
4831static struct hw_module_methods_t hal_module_methods = {
4832 .open = adev_open,
4833};
4834
4835struct audio_module HAL_MODULE_INFO_SYM = {
4836 .common = {
4837 .tag = HARDWARE_MODULE_TAG,
4838 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4839 .hal_api_version = HARDWARE_HAL_API_VERSION,
4840 .id = AUDIO_HARDWARE_MODULE_ID,
4841 .name = "QCOM Audio HAL",
4842 .author = "Code Aurora Forum",
4843 .methods = &hal_module_methods,
4844 },
4845};