blob: 77a693cf3fb26fb30f4c3f5a49f5de2531ded968 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
vivek mehtaa51fd402016-02-04 19:49:33 -08002 * Copyright (C) 2013-2016 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "audio_hw_primary"
Haynes Mathew George03c40102016-01-29 17:57:48 -080018#define ATRACE_TAG ATRACE_TAG_AUDIO
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080019/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070020/*#define VERY_VERY_VERBOSE_LOGGING*/
21#ifdef VERY_VERY_VERBOSE_LOGGING
22#define ALOGVV ALOGV
23#else
24#define ALOGVV(a...) do { } while(0)
25#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080026
27#include <errno.h>
28#include <pthread.h>
29#include <stdint.h>
30#include <sys/time.h>
31#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080032#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070033#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070034#include <sys/resource.h>
35#include <sys/prctl.h>
Kevin Rocardb5c28192017-05-02 15:30:20 -070036#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
52#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070076#define PROXY_OPEN_RETRY_COUNT 100
77#define PROXY_OPEN_WAIT_TIME 20
78
vivek mehtadae44712015-07-27 14:13:18 -070079#define MIN_CHANNEL_COUNT 1
80#define DEFAULT_CHANNEL_COUNT 2
81
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
83#define MAX_CHANNEL_COUNT 1
84#else
vivek mehtadae44712015-07-27 14:13:18 -070085#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
86#define XSTR(x) STR(x)
87#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#endif
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
101
Andy Hung31aca912014-03-20 17:14:59 -0700102/* This constant enables extended precision handling.
103 * TODO The flag is off until more testing is done.
104 */
105static const bool k_enable_extended_precision = false;
106
Eric Laurentb23d5282013-05-14 15:27:20 -0700107struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -0700108 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700109 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
110 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
111 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
112 .format = PCM_FORMAT_S16_LE,
113 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
114 .stop_threshold = INT_MAX,
115 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
116};
117
118struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700119 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700120 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
121 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
122 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
123 .format = PCM_FORMAT_S16_LE,
124 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
125 .stop_threshold = INT_MAX,
126 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
127};
128
Haynes Mathew George03c40102016-01-29 17:57:48 -0800129static int af_period_multiplier = 4;
130struct pcm_config pcm_config_rt = {
131 .channels = DEFAULT_CHANNEL_COUNT,
132 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
133 .period_size = ULL_PERIOD_SIZE, //1 ms
134 .period_count = 512, //=> buffer size is 512ms
135 .format = PCM_FORMAT_S16_LE,
136 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
137 .stop_threshold = INT_MAX,
138 .silence_threshold = 0,
139 .silence_size = 0,
140 .avail_min = ULL_PERIOD_SIZE, //1 ms
141};
142
Eric Laurentb23d5282013-05-14 15:27:20 -0700143struct pcm_config pcm_config_hdmi_multi = {
144 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
145 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
146 .period_size = HDMI_MULTI_PERIOD_SIZE,
147 .period_count = HDMI_MULTI_PERIOD_COUNT,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = 0,
150 .stop_threshold = INT_MAX,
151 .avail_min = 0,
152};
153
Eric Laurent0e46adf2016-12-16 12:49:24 -0800154struct pcm_config pcm_config_mmap_playback = {
155 .channels = DEFAULT_CHANNEL_COUNT,
156 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
157 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800158 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800159 .format = PCM_FORMAT_S16_LE,
160 .start_threshold = MMAP_PERIOD_SIZE*8,
161 .stop_threshold = INT32_MAX,
162 .silence_threshold = 0,
163 .silence_size = 0,
164 .avail_min = MMAP_PERIOD_SIZE, //1 ms
165};
166
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800167struct pcm_config pcm_config_hifi = {
168 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
169 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
170 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
171 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
172 .format = PCM_FORMAT_S24_3LE,
173 .start_threshold = 0,
174 .stop_threshold = INT_MAX,
175 .avail_min = 0,
176};
177
Eric Laurentb23d5282013-05-14 15:27:20 -0700178struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700179 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700180 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
181 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700182 .stop_threshold = INT_MAX,
183 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700184};
185
Haynes Mathew George03c40102016-01-29 17:57:48 -0800186struct pcm_config pcm_config_audio_capture_rt = {
187 .channels = DEFAULT_CHANNEL_COUNT,
188 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
189 .period_size = ULL_PERIOD_SIZE,
190 .period_count = 512,
191 .format = PCM_FORMAT_S16_LE,
192 .start_threshold = 0,
193 .stop_threshold = INT_MAX,
194 .silence_threshold = 0,
195 .silence_size = 0,
196 .avail_min = ULL_PERIOD_SIZE, //1 ms
197};
198
Eric Laurent0e46adf2016-12-16 12:49:24 -0800199struct pcm_config pcm_config_mmap_capture = {
200 .channels = DEFAULT_CHANNEL_COUNT,
201 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
202 .period_size = MMAP_PERIOD_SIZE,
Phil Burkbc991042017-02-24 08:06:44 -0800203 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
Eric Laurent0e46adf2016-12-16 12:49:24 -0800204 .format = PCM_FORMAT_S16_LE,
205 .start_threshold = 0,
206 .stop_threshold = INT_MAX,
207 .silence_threshold = 0,
208 .silence_size = 0,
209 .avail_min = MMAP_PERIOD_SIZE, //1 ms
210};
211
vivek mehtaa68fea62017-06-08 19:04:02 -0700212struct pcm_config pcm_config_voip = {
213 .channels = 1,
214 .period_count = 2,
215 .format = PCM_FORMAT_S16_LE,
216 .stop_threshold = INT_MAX,
217 .avail_min = 0,
218};
219
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700220#define AFE_PROXY_CHANNEL_COUNT 2
221#define AFE_PROXY_SAMPLING_RATE 48000
222
223#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
224#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
225
226struct pcm_config pcm_config_afe_proxy_playback = {
227 .channels = AFE_PROXY_CHANNEL_COUNT,
228 .rate = AFE_PROXY_SAMPLING_RATE,
229 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
230 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
233 .stop_threshold = INT_MAX,
234 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
235};
236
237#define AFE_PROXY_RECORD_PERIOD_SIZE 768
238#define AFE_PROXY_RECORD_PERIOD_COUNT 4
239
240struct pcm_config pcm_config_afe_proxy_record = {
241 .channels = AFE_PROXY_CHANNEL_COUNT,
242 .rate = AFE_PROXY_SAMPLING_RATE,
243 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
244 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
245 .format = PCM_FORMAT_S16_LE,
246 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
247 .stop_threshold = INT_MAX,
248 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
249};
250
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700251const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700252 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
253 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800254 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700255 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700256 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700257 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800258 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700259
Eric Laurentb23d5282013-05-14 15:27:20 -0700260 [USECASE_AUDIO_RECORD] = "audio-record",
261 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Eric Laurent0e46adf2016-12-16 12:49:24 -0800262 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George569b7482017-05-08 14:44:27 -0700263 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700264
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800265 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
266 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700267
Eric Laurentb23d5282013-05-14 15:27:20 -0700268 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700269 [USECASE_VOICE2_CALL] = "voice2-call",
270 [USECASE_VOLTE_CALL] = "volte-call",
271 [USECASE_QCHAT_CALL] = "qchat-call",
272 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800273 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
274 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700275
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700276 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
277 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
278
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700279 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
280 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
vivek mehta781065c2017-04-04 12:55:01 -0700281
282 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
283 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
284 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
285
vivek mehtaa68fea62017-06-08 19:04:02 -0700286 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
287 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Eric Laurentb23d5282013-05-14 15:27:20 -0700288};
289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800290
291#define STRING_TO_ENUM(string) { #string, string }
292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800293struct string_to_enum {
294 const char *name;
295 uint32_t value;
296};
297
Haynes Mathew George569b7482017-05-08 14:44:27 -0700298static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
300 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
301 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700302 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
303 //TBD - string values for channel_in > 2?
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800304};
305
Haynes Mathew George5191a852013-09-11 14:19:36 -0700306static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700307static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700308static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700309static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700310//cache last MBDRC cal step level
311static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700312
Andy Hung9e737de2017-05-22 10:51:22 -0700313// TODO: Consider moving this to a pthread_once() if we have more
314// static initialization required.
315static bool is_userdebug_or_eng_build() {
316 char value[PROPERTY_VALUE_MAX];
317 (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
318 return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
319}
320
Haynes Mathew George03c40102016-01-29 17:57:48 -0800321static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
322 int flags __unused)
323{
324 int dir = 0;
325 switch (uc_id) {
326 case USECASE_AUDIO_RECORD_LOW_LATENCY:
327 dir = 1;
328 case USECASE_AUDIO_PLAYBACK_ULL:
329 break;
330 default:
331 return false;
332 }
333
334 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
335 PCM_PLAYBACK : PCM_CAPTURE);
336 if (adev->adm_is_noirq_avail)
337 return adev->adm_is_noirq_avail(adev->adm_data,
338 adev->snd_card, dev_id, dir);
339 return false;
340}
341
342static void register_out_stream(struct stream_out *out)
343{
344 struct audio_device *adev = out->dev;
345 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
346 return;
347
348 if (!adev->adm_register_output_stream)
349 return;
350
351 adev->adm_register_output_stream(adev->adm_data,
352 out->handle,
353 out->flags);
354
355 if (!adev->adm_set_config)
356 return;
357
358 if (out->realtime) {
359 adev->adm_set_config(adev->adm_data,
360 out->handle,
361 out->pcm, &out->config);
362 }
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime) {
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383 }
384}
385
386static void request_out_focus(struct stream_out *out, long ns)
387{
388 struct audio_device *adev = out->dev;
389
Haynes Mathew George03c40102016-01-29 17:57:48 -0800390 if (adev->adm_request_focus_v2) {
391 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
392 } else if (adev->adm_request_focus) {
393 adev->adm_request_focus(adev->adm_data, out->handle);
394 }
395}
396
397static void request_in_focus(struct stream_in *in, long ns)
398{
399 struct audio_device *adev = in->dev;
400
Haynes Mathew George03c40102016-01-29 17:57:48 -0800401 if (adev->adm_request_focus_v2) {
402 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
403 } else if (adev->adm_request_focus) {
404 adev->adm_request_focus(adev->adm_data, in->capture_handle);
405 }
406}
407
408static void release_out_focus(struct stream_out *out, long ns __unused)
409{
410 struct audio_device *adev = out->dev;
411
412 if (adev->adm_abandon_focus)
413 adev->adm_abandon_focus(adev->adm_data, out->handle);
414}
415
416static void release_in_focus(struct stream_in *in, long ns __unused)
417{
418 struct audio_device *adev = in->dev;
419 if (adev->adm_abandon_focus)
420 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
421}
422
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700423static int parse_snd_card_status(struct str_parms * parms, int * card,
424 card_status_t * status)
425{
426 char value[32]={0};
427 char state[32]={0};
428
429 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
430
431 if (ret < 0)
432 return -1;
433
434 // sscanf should be okay as value is of max length 32.
435 // same as sizeof state.
436 if (sscanf(value, "%d,%s", card, state) < 2)
437 return -1;
438
439 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
440 CARD_STATUS_OFFLINE;
441 return 0;
442}
443
vivek mehta1a9b7c02015-06-25 11:49:38 -0700444__attribute__ ((visibility ("default")))
445bool audio_hw_send_gain_dep_calibration(int level) {
446 bool ret_val = false;
447 ALOGV("%s: enter ... ", __func__);
448
449 pthread_mutex_lock(&adev_init_lock);
450
451 if (adev != NULL && adev->platform != NULL) {
452 pthread_mutex_lock(&adev->lock);
453 ret_val = platform_send_gain_dep_cal(adev->platform, level);
454 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700455
456 // if cal set fails, cache level info
457 // if cal set succeds, reset known last cal set
458 if (!ret_val)
459 last_known_cal_step = level;
460 else if (last_known_cal_step != -1)
461 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700462 } else {
463 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
464 }
465
466 pthread_mutex_unlock(&adev_init_lock);
467
468 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
469 return ret_val;
470}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700471
vivek mehtaa8d7c922016-05-25 14:40:44 -0700472__attribute__ ((visibility ("default")))
473int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
474 int table_size) {
475 int ret_val = 0;
476 ALOGV("%s: enter ... ", __func__);
477
478 pthread_mutex_lock(&adev_init_lock);
479 if (adev == NULL) {
480 ALOGW("%s: adev is NULL .... ", __func__);
481 goto done;
482 }
483
484 pthread_mutex_lock(&adev->lock);
485 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
486 pthread_mutex_unlock(&adev->lock);
487done:
488 pthread_mutex_unlock(&adev_init_lock);
489 ALOGV("%s: exit ... ", __func__);
490 return ret_val;
491}
492
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700493static bool is_supported_format(audio_format_t format)
494{
Eric Laurent8251ac82014-07-23 11:00:25 -0700495 switch (format) {
496 case AUDIO_FORMAT_MP3:
497 case AUDIO_FORMAT_AAC_LC:
498 case AUDIO_FORMAT_AAC_HE_V1:
499 case AUDIO_FORMAT_AAC_HE_V2:
500 return true;
501 default:
502 break;
503 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700504 return false;
505}
506
Haynes Mathew George03c40102016-01-29 17:57:48 -0800507static inline bool is_mmap_usecase(audio_usecase_t uc_id)
508{
509 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
510 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
511}
512
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700513static int get_snd_codec_id(audio_format_t format)
514{
515 int id = 0;
516
Eric Laurent8251ac82014-07-23 11:00:25 -0700517 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700518 case AUDIO_FORMAT_MP3:
519 id = SND_AUDIOCODEC_MP3;
520 break;
521 case AUDIO_FORMAT_AAC:
522 id = SND_AUDIOCODEC_AAC;
523 break;
524 default:
525 ALOGE("%s: Unsupported audio format", __func__);
526 }
527
528 return id;
529}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800530
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800531static int audio_ssr_status(struct audio_device *adev)
532{
533 int ret = 0;
534 struct mixer_ctl *ctl;
535 const char *mixer_ctl_name = "Audio SSR Status";
536
537 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
538 ret = mixer_ctl_get_value(ctl, 0);
539 ALOGD("%s: value: %d", __func__, ret);
540 return ret;
541}
542
vivek mehta4a824772017-06-08 19:05:49 -0700543static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
544{
545 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
546}
547
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800548int enable_audio_route(struct audio_device *adev,
549 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700551 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800553
554 if (usecase == NULL)
555 return -EINVAL;
556
557 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
558
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800559 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700560 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800561 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800563
Yamit Mehtae3b99562016-09-16 22:44:00 +0530564 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800565 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800566 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500567 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700568 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700569 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800571 ALOGV("%s: exit", __func__);
572 return 0;
573}
574
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800575int disable_audio_route(struct audio_device *adev,
576 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700578 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800580
581 if (usecase == NULL)
582 return -EINVAL;
583
584 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585 if (usecase->type == PCM_CAPTURE)
586 snd_device = usecase->in_snd_device;
587 else
588 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800589 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500590 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700591 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700592 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800594 ALOGV("%s: exit", __func__);
595 return 0;
596}
597
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800598int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700599 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800600{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700601 int i, num_devices = 0;
602 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800603 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800604 if (snd_device < SND_DEVICE_MIN ||
605 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800606 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800607 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800608 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700609
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700610 platform_send_audio_calibration(adev->platform, snd_device);
611
vivek mehtade4849c2016-03-03 17:23:38 -0800612 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700613 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700614 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800615 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 }
617
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700618 /* due to the possibility of calibration overwrite between listen
619 and audio, notify sound trigger hal before audio calibration is sent */
620 audio_extn_sound_trigger_update_device_status(snd_device,
621 ST_EVENT_SND_DEVICE_BUSY);
622
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700623 if (audio_extn_spkr_prot_is_enabled())
624 audio_extn_spkr_prot_calib_cancel(adev);
625
zhaoyang yin4211fad2015-06-04 21:13:25 +0800626 audio_extn_dsm_feedback_enable(adev, snd_device, true);
627
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700628 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
629 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
630 audio_extn_spkr_prot_is_enabled()) {
631 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800632 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700633 }
634 if (audio_extn_spkr_prot_start_processing(snd_device)) {
635 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800636 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700637 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700638 } else if (platform_can_split_snd_device(snd_device,
639 &num_devices,
640 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700641 for (i = 0; i < num_devices; i++) {
642 enable_snd_device(adev, new_snd_devices[i]);
643 }
vivek mehtab6506412015-08-07 16:55:17 -0700644 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700645 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800646 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
647 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
648 ALOGE(" %s: Invalid sound device returned", __func__);
649 goto on_error;
650 }
Ed Tam70b5c142016-03-21 19:14:29 -0700651
Eric Laurent2e140aa2016-06-30 17:14:46 -0700652 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800653 audio_route_apply_and_update_path(adev->audio_route, device_name);
654 }
655on_success:
656 adev->snd_dev_ref_cnt[snd_device]++;
657 ret_val = 0;
658on_error:
659 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800660}
661
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800662int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700663 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800664{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700665 int i, num_devices = 0;
666 snd_device_t new_snd_devices[2];
667
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800668 if (snd_device < SND_DEVICE_MIN ||
669 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800670 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800671 return -EINVAL;
672 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700673 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
674 ALOGE("%s: device ref cnt is already 0", __func__);
675 return -EINVAL;
676 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800677 audio_extn_tfa_98xx_disable_speaker(snd_device);
678
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 adev->snd_dev_ref_cnt[snd_device]--;
680 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800681 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700682 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
683 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
684 audio_extn_spkr_prot_is_enabled()) {
685 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700686 } else if (platform_can_split_snd_device(snd_device,
687 &num_devices,
688 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700689 for (i = 0; i < num_devices; i++) {
690 disable_snd_device(adev, new_snd_devices[i]);
691 }
vivek mehtab6506412015-08-07 16:55:17 -0700692 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700693 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800694 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
695 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
696 ALOGE(" %s: Invalid sound device returned", __func__);
697 return -EINVAL;
698 }
699
Eric Laurent2e140aa2016-06-30 17:14:46 -0700700 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800701 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700702 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700703 audio_extn_sound_trigger_update_device_status(snd_device,
704 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 }
vivek mehtab6506412015-08-07 16:55:17 -0700706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800707 return 0;
708}
709
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700710/*
711 legend:
712 uc - existing usecase
713 new_uc - new usecase
714 d1, d11, d2 - SND_DEVICE enums
715 a1, a2 - corresponding ANDROID device enums
716 B, B1, B2 - backend strings
717
718case 1
719 uc->dev d1 (a1) B1
720 new_uc->dev d1 (a1), d2 (a2) B1, B2
721
722 resolution: disable and enable uc->dev on d1
723
724case 2
725 uc->dev d1 (a1) B1
726 new_uc->dev d11 (a1) B1
727
728 resolution: need to switch uc since d1 and d11 are related
729 (e.g. speaker and voice-speaker)
730 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
731
732case 3
733 uc->dev d1 (a1) B1
734 new_uc->dev d2 (a2) B2
735
736 resolution: no need to switch uc
737
738case 4
739 uc->dev d1 (a1) B
740 new_uc->dev d2 (a2) B
741
742 resolution: disable enable uc-dev on d2 since backends match
743 we cannot enable two streams on two different devices if they
744 share the same backend. e.g. if offload is on speaker device using
745 QUAD_MI2S backend and a low-latency stream is started on voice-handset
746 using the same backend, offload must also be switched to voice-handset.
747
748case 5
749 uc->dev d1 (a1) B
750 new_uc->dev d1 (a1), d2 (a2) B
751
752 resolution: disable enable uc-dev on d2 since backends match
753 we cannot enable two streams on two different devices if they
754 share the same backend.
755
756case 6
757 uc->dev d1 a1 B1
758 new_uc->dev d2 a1 B2
759
760 resolution: no need to switch
761
762case 7
763
764 uc->dev d1 (a1), d2 (a2) B1, B2
765 new_uc->dev d1 B1
766
767 resolution: no need to switch
768
769*/
770static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
771 struct audio_usecase *new_uc,
772 snd_device_t new_snd_device)
773{
774 audio_devices_t a1 = uc->stream.out->devices;
775 audio_devices_t a2 = new_uc->stream.out->devices;
776
777 snd_device_t d1 = uc->out_snd_device;
778 snd_device_t d2 = new_snd_device;
779
780 // Treat as a special case when a1 and a2 are not disjoint
781 if ((a1 != a2) && (a1 & a2)) {
782 snd_device_t d3[2];
783 int num_devices = 0;
784 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
785 &num_devices,
786 d3);
787 if (ret < 0) {
788 if (ret != -ENOSYS) {
789 ALOGW("%s failed to split snd_device %d",
790 __func__,
791 popcount(a1) > 1 ? d1 : d2);
792 }
793 goto end;
794 }
795
796 // NB: case 7 is hypothetical and isn't a practical usecase yet.
797 // But if it does happen, we need to give priority to d2 if
798 // the combo devices active on the existing usecase share a backend.
799 // This is because we cannot have a usecase active on a combo device
800 // and a new usecase requests one device in this combo pair.
801 if (platform_check_backends_match(d3[0], d3[1])) {
802 return d2; // case 5
803 } else {
804 return d1; // case 1
805 }
806 } else {
807 if (platform_check_backends_match(d1, d2)) {
808 return d2; // case 2, 4
809 } else {
810 return d1; // case 6, 3
811 }
812 }
813
814end:
815 return d2; // return whatever was calculated before.
816}
817
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700818static void check_and_route_playback_usecases(struct audio_device *adev,
819 struct audio_usecase *uc_info,
820 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700821{
822 struct listnode *node;
823 struct audio_usecase *usecase;
824 bool switch_device[AUDIO_USECASE_MAX];
825 int i, num_uc_to_switch = 0;
826
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700827 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
828 uc_info,
829 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700830
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831 /*
832 * This function is to make sure that all the usecases that are active on
833 * the hardware codec backend are always routed to any one device that is
834 * handled by the hardware codec.
835 * For example, if low-latency and deep-buffer usecases are currently active
836 * on speaker and out_set_parameters(headset) is received on low-latency
837 * output, then we have to make sure deep-buffer is also switched to headset,
838 * because of the limitation that both the devices cannot be enabled
839 * at the same time as they share the same backend.
840 */
841 /* Disable all the usecases on the shared backend other than the
842 specified usecase */
843 for (i = 0; i < AUDIO_USECASE_MAX; i++)
844 switch_device[i] = false;
845
846 list_for_each(node, &adev->usecase_list) {
847 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700848 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
849 continue;
850
851 if (force_routing ||
852 (usecase->out_snd_device != snd_device &&
853 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
854 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
856 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700857 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700858 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700859 switch_device[usecase->id] = true;
860 num_uc_to_switch++;
861 }
862 }
863
864 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 list_for_each(node, &adev->usecase_list) {
866 usecase = node_to_item(node, struct audio_usecase, list);
867 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700868 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900869 }
870 }
871
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700872 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900873 list_for_each(node, &adev->usecase_list) {
874 usecase = node_to_item(node, struct audio_usecase, list);
875 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700876 d_device = derive_playback_snd_device(usecase, uc_info,
877 snd_device);
878 enable_snd_device(adev, d_device);
879 /* Update the out_snd_device before enabling the audio route */
880 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 }
882 }
883
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 /* Re-route all the usecases on the shared backend other than the
885 specified usecase to new snd devices */
886 list_for_each(node, &adev->usecase_list) {
887 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700888 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700889 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 }
891 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 }
893}
894
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700895static void check_and_route_capture_usecases(struct audio_device *adev,
896 struct audio_usecase *uc_info,
897 snd_device_t snd_device)
898{
899 struct listnode *node;
900 struct audio_usecase *usecase;
901 bool switch_device[AUDIO_USECASE_MAX];
902 int i, num_uc_to_switch = 0;
903
vivek mehta4ed66e62016-04-15 23:33:34 -0700904 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
905
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700906 /*
907 * This function is to make sure that all the active capture usecases
908 * are always routed to the same input sound device.
909 * For example, if audio-record and voice-call usecases are currently
910 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
911 * is received for voice call then we have to make sure that audio-record
912 * usecase is also switched to earpiece i.e. voice-dmic-ef,
913 * because of the limitation that two devices cannot be enabled
914 * at the same time if they share the same backend.
915 */
916 for (i = 0; i < AUDIO_USECASE_MAX; i++)
917 switch_device[i] = false;
918
919 list_for_each(node, &adev->usecase_list) {
920 usecase = node_to_item(node, struct audio_usecase, list);
921 if (usecase->type != PCM_PLAYBACK &&
922 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700923 usecase->in_snd_device != snd_device &&
924 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700925 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
926 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700927 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700928 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700929 switch_device[usecase->id] = true;
930 num_uc_to_switch++;
931 }
932 }
933
934 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700935 list_for_each(node, &adev->usecase_list) {
936 usecase = node_to_item(node, struct audio_usecase, list);
937 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700938 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700939 }
940 }
941
942 list_for_each(node, &adev->usecase_list) {
943 usecase = node_to_item(node, struct audio_usecase, list);
944 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700945 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700946 }
947 }
948
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 /* Re-route all the usecases on the shared backend other than the
950 specified usecase to new snd devices */
951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
953 /* Update the in_snd_device only before enabling the audio route */
954 if (switch_device[usecase->id] ) {
955 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700956 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700957 }
958 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700959 }
960}
961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800962/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700963static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800964{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700965 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700966 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800967
968 switch (channels) {
969 /*
970 * Do not handle stereo output in Multi-channel cases
971 * Stereo case is handled in normal playback path
972 */
973 case 6:
974 ALOGV("%s: HDMI supports 5.1", __func__);
975 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
976 break;
977 case 8:
978 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
979 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
980 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
981 break;
982 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700983 ALOGE("HDMI does not support multi channel playback");
984 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985 break;
986 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700987 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800988}
989
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700990static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
991 uint32_t *supported_sample_rates __unused,
992 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800993{
Haynes Mathew George569b7482017-05-08 14:44:27 -0700994 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
995 supported_sample_rates,
996 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800997#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -0700998 for (ssize_t i=0; i<count; i++) {
999 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1000 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001001 }
1002#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001003 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001004}
1005
Haynes Mathew George569b7482017-05-08 14:44:27 -07001006static int read_usb_sup_channel_masks(bool is_playback,
1007 audio_channel_mask_t *supported_channel_masks,
1008 uint32_t max_masks __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001009{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001010 int channels = audio_extn_usb_get_max_channels(is_playback);
1011 if (is_playback) {
1012 supported_channel_masks[0] =
1013 channels < 3 ? audio_channel_out_mask_from_count(channels) :
1014 audio_channel_mask_for_index_assignment_from_count(channels);
1015 } else {
1016 supported_channel_masks[0] = audio_channel_in_mask_from_count(channels);
1017 }
1018 ALOGV("%s: %s supported ch %d", __func__,
1019 is_playback ? "P" : "C", channels);
1020 return 1;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001021}
1022
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001023static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001024 audio_format_t *supported_formats,
1025 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001026{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001027 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001028 switch (bitwidth) {
1029 case 24:
1030 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001031 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001032 break;
1033 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001034 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001035 break;
1036 case 16:
1037 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001038 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001039 break;
1040 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001041 ALOGV("%s: %s supported format %d", __func__,
1042 is_playback ? "P" : "C", bitwidth);
1043 return 1;
1044}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001045
Haynes Mathew George569b7482017-05-08 14:44:27 -07001046static int read_usb_sup_params_and_compare(bool is_playback,
1047 audio_format_t *format,
1048 audio_format_t *supported_formats,
1049 uint32_t max_formats,
1050 audio_channel_mask_t *mask,
1051 audio_channel_mask_t *supported_channel_masks,
1052 uint32_t max_masks,
1053 uint32_t *rate,
1054 uint32_t *supported_sample_rates,
1055 uint32_t max_rates) {
1056 int ret = 0;
1057 int num_formats;
1058 int num_masks;
1059 int num_rates;
1060 int i;
1061
1062 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1063 max_formats);
1064 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1065 max_masks);
1066 num_rates = read_usb_sup_sample_rates(is_playback,
1067 supported_sample_rates, max_rates);
1068
1069#define LUT(table, len, what, dflt) \
1070 for (i=0; i<len && (table[i] != what); i++); \
1071 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1072
1073 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1074 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1075 LUT(supported_sample_rates, num_rates, *rate, 0);
1076
1077#undef LUT
1078 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001079}
1080
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001081static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1082{
1083 struct audio_usecase *usecase;
1084 struct listnode *node;
1085
1086 list_for_each(node, &adev->usecase_list) {
1087 usecase = node_to_item(node, struct audio_usecase, list);
1088 if (usecase->type == VOICE_CALL) {
1089 ALOGV("%s: usecase id %d", __func__, usecase->id);
1090 return usecase->id;
1091 }
1092 }
1093 return USECASE_INVALID;
1094}
1095
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001096struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1097 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098{
1099 struct audio_usecase *usecase;
1100 struct listnode *node;
1101
1102 list_for_each(node, &adev->usecase_list) {
1103 usecase = node_to_item(node, struct audio_usecase, list);
1104 if (usecase->id == uc_id)
1105 return usecase;
1106 }
1107 return NULL;
1108}
1109
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001110int select_devices(struct audio_device *adev,
1111 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001113 snd_device_t out_snd_device = SND_DEVICE_NONE;
1114 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001115 struct audio_usecase *usecase = NULL;
1116 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001117 struct audio_usecase *hfp_usecase = NULL;
1118 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001119 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001120 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001122 usecase = get_usecase_from_list(adev, uc_id);
1123 if (usecase == NULL) {
1124 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1125 return -EINVAL;
1126 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001128 if ((usecase->type == VOICE_CALL) ||
1129 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001130 out_snd_device = platform_get_output_snd_device(adev->platform,
1131 usecase->stream.out->devices);
1132 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 usecase->devices = usecase->stream.out->devices;
1134 } else {
1135 /*
1136 * If the voice call is active, use the sound devices of voice call usecase
1137 * so that it would not result any device switch. All the usecases will
1138 * be switched to new device when select_devices() is called for voice call
1139 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001140 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001141 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001142 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001143 vc_usecase = get_usecase_from_list(adev,
1144 get_voice_usecase_id_from_list(adev));
1145 if ((vc_usecase != NULL) &&
1146 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1147 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001148 in_snd_device = vc_usecase->in_snd_device;
1149 out_snd_device = vc_usecase->out_snd_device;
1150 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001151 } else if (audio_extn_hfp_is_active(adev)) {
1152 hfp_ucid = audio_extn_hfp_get_usecase();
1153 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1154 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1155 in_snd_device = hfp_usecase->in_snd_device;
1156 out_snd_device = hfp_usecase->out_snd_device;
1157 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158 }
1159 if (usecase->type == PCM_PLAYBACK) {
1160 usecase->devices = usecase->stream.out->devices;
1161 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001162 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001163 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001164 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001165 if (usecase->stream.out == adev->primary_output &&
1166 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001167 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1168 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001169 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001170 select_devices(adev, adev->active_input->usecase);
1171 }
1172 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 } else if (usecase->type == PCM_CAPTURE) {
1174 usecase->devices = usecase->stream.in->device;
1175 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001176 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001177 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001178 if (adev->active_input &&
1179 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1180 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001181 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001182 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1183 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1184 } else if (adev->primary_output) {
1185 out_device = adev->primary_output->devices;
1186 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001187 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001188 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001189 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001190 }
1191 }
1192
1193 if (out_snd_device == usecase->out_snd_device &&
1194 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001195 return 0;
1196 }
1197
Eric Laurent2bafff12016-03-17 12:17:23 -07001198 if (out_snd_device != SND_DEVICE_NONE &&
1199 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1200 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1201 __func__,
1202 use_case_table[uc_id],
1203 adev->last_logged_snd_device[uc_id][0],
1204 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1205 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1206 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1207 -1,
1208 out_snd_device,
1209 platform_get_snd_device_name(out_snd_device),
1210 platform_get_snd_device_acdb_id(out_snd_device));
1211 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1212 }
1213 if (in_snd_device != SND_DEVICE_NONE &&
1214 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1215 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1216 __func__,
1217 use_case_table[uc_id],
1218 adev->last_logged_snd_device[uc_id][1],
1219 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1220 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1221 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1222 -1,
1223 in_snd_device,
1224 platform_get_snd_device_name(in_snd_device),
1225 platform_get_snd_device_acdb_id(in_snd_device));
1226 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1227 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229 /*
1230 * Limitation: While in call, to do a device switch we need to disable
1231 * and enable both RX and TX devices though one of them is same as current
1232 * device.
1233 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001234 if ((usecase->type == VOICE_CALL) &&
1235 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1236 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001237 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001238 /* Disable sidetone only if voice call already exists */
1239 if (voice_is_call_state_active(adev))
1240 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001241 }
1242
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001243 /* Disable current sound devices */
1244 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001245 disable_audio_route(adev, usecase);
1246 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247 }
1248
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001249 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001250 disable_audio_route(adev, usecase);
1251 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252 }
1253
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001254 /* Applicable only on the targets that has external modem.
1255 * New device information should be sent to modem before enabling
1256 * the devices to reduce in-call device switch time.
1257 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001258 if ((usecase->type == VOICE_CALL) &&
1259 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1260 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001261 status = platform_switch_voice_call_enable_device_config(adev->platform,
1262 out_snd_device,
1263 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001264 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001265
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001266 /* Enable new sound devices */
1267 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001268 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001269 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001270 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001271 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272 }
1273
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001274 if (in_snd_device != SND_DEVICE_NONE) {
1275 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001276 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001277 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001278
Eric Laurentb23d5282013-05-14 15:27:20 -07001279 if (usecase->type == VOICE_CALL)
1280 status = platform_switch_voice_call_device_post(adev->platform,
1281 out_snd_device,
1282 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001283
sangwoo170731f2013-06-08 15:36:36 +09001284 usecase->in_snd_device = in_snd_device;
1285 usecase->out_snd_device = out_snd_device;
1286
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001287 audio_extn_tfa_98xx_set_mode();
1288
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001289 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001290
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001291 /* Applicable only on the targets that has external modem.
1292 * Enable device command should be sent to modem only after
1293 * enabling voice call mixer controls
1294 */
vivek mehta765eb642015-08-07 19:46:06 -07001295 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001296 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1297 out_snd_device,
1298 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001299 /* Enable sidetone only if voice call already exists */
1300 if (voice_is_call_state_active(adev))
1301 voice_set_sidetone(adev, out_snd_device, true);
1302 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001304 return status;
1305}
1306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001307static int stop_input_stream(struct stream_in *in)
1308{
1309 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 struct audio_usecase *uc_info;
1311 struct audio_device *adev = in->dev;
1312
Eric Laurentc8400632013-02-14 19:04:54 -08001313 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314
Eric Laurent994a6932013-07-17 11:51:42 -07001315 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001317 uc_info = get_usecase_from_list(adev, in->usecase);
1318 if (uc_info == NULL) {
1319 ALOGE("%s: Could not find the usecase (%d) in the list",
1320 __func__, in->usecase);
1321 return -EINVAL;
1322 }
1323
vivek mehta781065c2017-04-04 12:55:01 -07001324 /* Close in-call recording streams */
1325 voice_check_and_stop_incall_rec_usecase(adev, in);
1326
Eric Laurent150dbfe2013-02-27 14:31:02 -08001327 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001328 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329
1330 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001331 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001332
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001333 list_remove(&uc_info->list);
1334 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001335
Eric Laurent994a6932013-07-17 11:51:42 -07001336 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001337 return ret;
1338}
1339
1340int start_input_stream(struct stream_in *in)
1341{
1342 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001343 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 struct audio_usecase *uc_info;
1345 struct audio_device *adev = in->dev;
1346
Eric Laurent994a6932013-07-17 11:51:42 -07001347 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001348
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001349 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1350 return -EIO;
1351
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001352 if (in->card_status == CARD_STATUS_OFFLINE ||
1353 adev->card_status == CARD_STATUS_OFFLINE) {
1354 ALOGW("in->card_status or adev->card_status offline, try again");
1355 ret = -EAGAIN;
1356 goto error_config;
1357 }
1358
vivek mehta781065c2017-04-04 12:55:01 -07001359 /* Check if source matches incall recording usecase criteria */
1360 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1361 if (ret)
1362 goto error_config;
1363 else
1364 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1365
Eric Laurentb23d5282013-05-14 15:27:20 -07001366 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367 if (in->pcm_device_id < 0) {
1368 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1369 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001370 ret = -EINVAL;
1371 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001373
1374 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1376 uc_info->id = in->usecase;
1377 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001378 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001379 uc_info->devices = in->device;
1380 uc_info->in_snd_device = SND_DEVICE_NONE;
1381 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001382
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001383 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001384
1385 audio_extn_perf_lock_acquire();
1386
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001387 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388
Eric Laurent0e46adf2016-12-16 12:49:24 -08001389 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001390 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001391 ALOGE("%s: pcm stream not ready", __func__);
1392 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001393 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001394 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001395 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001396 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1397 goto error_open;
1398 }
1399 } else {
1400 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1401 unsigned int pcm_open_retry_count = 0;
1402
1403 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1404 flags |= PCM_MMAP | PCM_NOIRQ;
1405 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1406 } else if (in->realtime) {
1407 flags |= PCM_MMAP | PCM_NOIRQ;
1408 }
1409
1410 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1411 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1412
1413 while (1) {
1414 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1415 flags, &in->config);
1416 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1417 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1418 if (in->pcm != NULL) {
1419 pcm_close(in->pcm);
1420 in->pcm = NULL;
1421 }
1422 if (pcm_open_retry_count-- == 0) {
1423 ret = -EIO;
1424 goto error_open;
1425 }
1426 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1427 continue;
1428 }
1429 break;
1430 }
1431
1432 ALOGV("%s: pcm_prepare", __func__);
1433 ret = pcm_prepare(in->pcm);
1434 if (ret < 0) {
1435 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001436 pcm_close(in->pcm);
1437 in->pcm = NULL;
1438 goto error_open;
1439 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001440 if (in->realtime) {
1441 ret = pcm_start(in->pcm);
1442 if (ret < 0) {
1443 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1444 pcm_close(in->pcm);
1445 in->pcm = NULL;
1446 goto error_open;
1447 }
1448 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001449 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001450 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001451 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001452 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001453
Eric Laurent0e46adf2016-12-16 12:49:24 -08001454 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001455
1456error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001458 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001459
1460error_config:
1461 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001462 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001463 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464}
1465
Eric Laurenta1478072015-09-21 17:21:52 -07001466void lock_input_stream(struct stream_in *in)
1467{
1468 pthread_mutex_lock(&in->pre_lock);
1469 pthread_mutex_lock(&in->lock);
1470 pthread_mutex_unlock(&in->pre_lock);
1471}
1472
1473void lock_output_stream(struct stream_out *out)
1474{
1475 pthread_mutex_lock(&out->pre_lock);
1476 pthread_mutex_lock(&out->lock);
1477 pthread_mutex_unlock(&out->pre_lock);
1478}
1479
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001480/* must be called with out->lock locked */
1481static int send_offload_cmd_l(struct stream_out* out, int command)
1482{
1483 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1484
1485 ALOGVV("%s %d", __func__, command);
1486
1487 cmd->cmd = command;
1488 list_add_tail(&out->offload_cmd_list, &cmd->node);
1489 pthread_cond_signal(&out->offload_cond);
1490 return 0;
1491}
1492
1493/* must be called iwth out->lock locked */
1494static void stop_compressed_output_l(struct stream_out *out)
1495{
1496 out->offload_state = OFFLOAD_STATE_IDLE;
1497 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001498 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001499 if (out->compr != NULL) {
1500 compress_stop(out->compr);
1501 while (out->offload_thread_blocked) {
1502 pthread_cond_wait(&out->cond, &out->lock);
1503 }
1504 }
1505}
1506
1507static void *offload_thread_loop(void *context)
1508{
1509 struct stream_out *out = (struct stream_out *) context;
1510 struct listnode *item;
1511
1512 out->offload_state = OFFLOAD_STATE_IDLE;
1513 out->playback_started = 0;
1514
1515 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1516 set_sched_policy(0, SP_FOREGROUND);
1517 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1518
1519 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001520 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001521 for (;;) {
1522 struct offload_cmd *cmd = NULL;
1523 stream_callback_event_t event;
1524 bool send_callback = false;
1525
1526 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1527 __func__, list_empty(&out->offload_cmd_list),
1528 out->offload_state);
1529 if (list_empty(&out->offload_cmd_list)) {
1530 ALOGV("%s SLEEPING", __func__);
1531 pthread_cond_wait(&out->offload_cond, &out->lock);
1532 ALOGV("%s RUNNING", __func__);
1533 continue;
1534 }
1535
1536 item = list_head(&out->offload_cmd_list);
1537 cmd = node_to_item(item, struct offload_cmd, node);
1538 list_remove(item);
1539
1540 ALOGVV("%s STATE %d CMD %d out->compr %p",
1541 __func__, out->offload_state, cmd->cmd, out->compr);
1542
1543 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1544 free(cmd);
1545 break;
1546 }
1547
1548 if (out->compr == NULL) {
1549 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001550 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001551 pthread_cond_signal(&out->cond);
1552 continue;
1553 }
1554 out->offload_thread_blocked = true;
1555 pthread_mutex_unlock(&out->lock);
1556 send_callback = false;
1557 switch(cmd->cmd) {
1558 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1559 compress_wait(out->compr, -1);
1560 send_callback = true;
1561 event = STREAM_CBK_EVENT_WRITE_READY;
1562 break;
1563 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001564 compress_next_track(out->compr);
1565 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001566 send_callback = true;
1567 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001568 /* Resend the metadata for next iteration */
1569 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001570 break;
1571 case OFFLOAD_CMD_DRAIN:
1572 compress_drain(out->compr);
1573 send_callback = true;
1574 event = STREAM_CBK_EVENT_DRAIN_READY;
1575 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001576 case OFFLOAD_CMD_ERROR:
1577 send_callback = true;
1578 event = STREAM_CBK_EVENT_ERROR;
1579 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001580 default:
1581 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1582 break;
1583 }
Eric Laurenta1478072015-09-21 17:21:52 -07001584 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001585 out->offload_thread_blocked = false;
1586 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001587 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001588 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001589 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001590 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001591 free(cmd);
1592 }
1593
1594 pthread_cond_signal(&out->cond);
1595 while (!list_empty(&out->offload_cmd_list)) {
1596 item = list_head(&out->offload_cmd_list);
1597 list_remove(item);
1598 free(node_to_item(item, struct offload_cmd, node));
1599 }
1600 pthread_mutex_unlock(&out->lock);
1601
1602 return NULL;
1603}
1604
1605static int create_offload_callback_thread(struct stream_out *out)
1606{
1607 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1608 list_init(&out->offload_cmd_list);
1609 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1610 offload_thread_loop, out);
1611 return 0;
1612}
1613
1614static int destroy_offload_callback_thread(struct stream_out *out)
1615{
Eric Laurenta1478072015-09-21 17:21:52 -07001616 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001617 stop_compressed_output_l(out);
1618 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1619
1620 pthread_mutex_unlock(&out->lock);
1621 pthread_join(out->offload_thread, (void **) NULL);
1622 pthread_cond_destroy(&out->offload_cond);
1623
1624 return 0;
1625}
1626
Eric Laurent07eeafd2013-10-06 12:52:49 -07001627static bool allow_hdmi_channel_config(struct audio_device *adev)
1628{
1629 struct listnode *node;
1630 struct audio_usecase *usecase;
1631 bool ret = true;
1632
1633 list_for_each(node, &adev->usecase_list) {
1634 usecase = node_to_item(node, struct audio_usecase, list);
1635 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1636 /*
1637 * If voice call is already existing, do not proceed further to avoid
1638 * disabling/enabling both RX and TX devices, CSD calls, etc.
1639 * Once the voice call done, the HDMI channels can be configured to
1640 * max channels of remaining use cases.
1641 */
1642 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001643 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001644 __func__);
1645 ret = false;
1646 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001647 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1648 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001649 "no change in HDMI channels", __func__);
1650 ret = false;
1651 break;
1652 }
1653 }
1654 }
1655 return ret;
1656}
1657
1658static int check_and_set_hdmi_channels(struct audio_device *adev,
1659 unsigned int channels)
1660{
1661 struct listnode *node;
1662 struct audio_usecase *usecase;
1663
1664 /* Check if change in HDMI channel config is allowed */
1665 if (!allow_hdmi_channel_config(adev))
1666 return 0;
1667
1668 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001669 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001670 return 0;
1671 }
1672
1673 platform_set_hdmi_channels(adev->platform, channels);
1674 adev->cur_hdmi_channels = channels;
1675
1676 /*
1677 * Deroute all the playback streams routed to HDMI so that
1678 * the back end is deactivated. Note that backend will not
1679 * be deactivated if any one stream is connected to it.
1680 */
1681 list_for_each(node, &adev->usecase_list) {
1682 usecase = node_to_item(node, struct audio_usecase, list);
1683 if (usecase->type == PCM_PLAYBACK &&
1684 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001685 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001686 }
1687 }
1688
1689 /*
1690 * Enable all the streams disabled above. Now the HDMI backend
1691 * will be activated with new channel configuration
1692 */
1693 list_for_each(node, &adev->usecase_list) {
1694 usecase = node_to_item(node, struct audio_usecase, list);
1695 if (usecase->type == PCM_PLAYBACK &&
1696 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001697 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001698 }
1699 }
1700
1701 return 0;
1702}
1703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704static int stop_output_stream(struct stream_out *out)
1705{
1706 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707 struct audio_usecase *uc_info;
1708 struct audio_device *adev = out->dev;
1709
Eric Laurent994a6932013-07-17 11:51:42 -07001710 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001711 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712 uc_info = get_usecase_from_list(adev, out->usecase);
1713 if (uc_info == NULL) {
1714 ALOGE("%s: Could not find the usecase (%d) in the list",
1715 __func__, out->usecase);
1716 return -EINVAL;
1717 }
1718
Haynes Mathew George41f86652014-06-17 14:22:15 -07001719 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1720 if (adev->visualizer_stop_output != NULL)
1721 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1722 if (adev->offload_effects_stop_output != NULL)
1723 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1724 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001725
Eric Laurent150dbfe2013-02-27 14:31:02 -08001726 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001727 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001728
1729 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001730 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001732 list_remove(&uc_info->list);
1733 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734
Eric Laurent0499d4f2014-08-25 22:39:29 -05001735 audio_extn_extspk_update(adev->extspk);
1736
Eric Laurent07eeafd2013-10-06 12:52:49 -07001737 /* Must be called after removing the usecase from list */
1738 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1739 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1740
Eric Laurent994a6932013-07-17 11:51:42 -07001741 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 return ret;
1743}
1744
1745int start_output_stream(struct stream_out *out)
1746{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 struct audio_usecase *uc_info;
1749 struct audio_device *adev = out->dev;
1750
Eric Laurent994a6932013-07-17 11:51:42 -07001751 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001752 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001753
1754 if (out->card_status == CARD_STATUS_OFFLINE ||
1755 adev->card_status == CARD_STATUS_OFFLINE) {
1756 ALOGW("out->card_status or adev->card_status offline, try again");
1757 ret = -EAGAIN;
1758 goto error_config;
1759 }
1760
Eric Laurentb23d5282013-05-14 15:27:20 -07001761 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762 if (out->pcm_device_id < 0) {
1763 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1764 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001765 ret = -EINVAL;
1766 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767 }
1768
1769 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1770 uc_info->id = out->usecase;
1771 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001772 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001773 uc_info->devices = out->devices;
1774 uc_info->in_snd_device = SND_DEVICE_NONE;
1775 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776
Eric Laurent07eeafd2013-10-06 12:52:49 -07001777 /* This must be called before adding this usecase to the list */
1778 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1779 check_and_set_hdmi_channels(adev, out->config.channels);
1780
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001781 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001783 audio_extn_perf_lock_acquire();
1784
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001785 select_devices(adev, out->usecase);
1786
Eric Laurent0499d4f2014-08-25 22:39:29 -05001787 audio_extn_extspk_update(adev->extspk);
1788
Andy Hung31aca912014-03-20 17:14:59 -07001789 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001790 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001791 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1792 out->pcm = NULL;
1793 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1794 COMPRESS_IN, &out->compr_config);
1795 if (out->compr && !is_compress_ready(out->compr)) {
1796 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1797 compress_close(out->compr);
1798 out->compr = NULL;
1799 ret = -EIO;
1800 goto error_open;
1801 }
1802 if (out->offload_callback)
1803 compress_nonblock(out->compr, out->non_blocking);
1804
1805 if (adev->visualizer_start_output != NULL)
1806 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1807 if (adev->offload_effects_start_output != NULL)
1808 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1809 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001810 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001811 ALOGE("%s: pcm stream not ready", __func__);
1812 goto error_open;
1813 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001814 ret = pcm_start(out->pcm);
1815 if (ret < 0) {
1816 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1817 goto error_open;
1818 }
1819 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001820 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001821 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001822
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001823 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1824 flags |= PCM_MMAP | PCM_NOIRQ;
1825 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001826 } else if (out->realtime) {
1827 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001828 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001829
1830 while (1) {
1831 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1832 flags, &out->config);
1833 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1834 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1835 if (out->pcm != NULL) {
1836 pcm_close(out->pcm);
1837 out->pcm = NULL;
1838 }
1839 if (pcm_open_retry_count-- == 0) {
1840 ret = -EIO;
1841 goto error_open;
1842 }
1843 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1844 continue;
1845 }
1846 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001847 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001848 ALOGV("%s: pcm_prepare", __func__);
1849 if (pcm_is_ready(out->pcm)) {
1850 ret = pcm_prepare(out->pcm);
1851 if (ret < 0) {
1852 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1853 pcm_close(out->pcm);
1854 out->pcm = NULL;
1855 goto error_open;
1856 }
1857 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001858 if (out->realtime) {
1859 ret = pcm_start(out->pcm);
1860 if (ret < 0) {
1861 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1862 pcm_close(out->pcm);
1863 out->pcm = NULL;
1864 goto error_open;
1865 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001866 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001867 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001868 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001869 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001870 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001871 audio_extn_utils_send_app_type_gain(out->dev,
1872 out->app_type_cfg.app_type,
1873 &out->app_type_cfg.gain[0]);
Eric Laurent994a6932013-07-17 11:51:42 -07001874 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001875 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001876error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001877 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001879error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001880 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881}
1882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883static int check_input_parameters(uint32_t sample_rate,
1884 audio_format_t format,
1885 int channel_count)
1886{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001887 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1888 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
1889 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED)) {
vivek mehtadae44712015-07-27 14:13:18 -07001890 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1891 return -EINVAL;
1892 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893
vivek mehtadae44712015-07-27 14:13:18 -07001894 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001895 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001896 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1897 return -EINVAL;
1898 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899
1900 switch (sample_rate) {
1901 case 8000:
1902 case 11025:
1903 case 12000:
1904 case 16000:
1905 case 22050:
1906 case 24000:
1907 case 32000:
1908 case 44100:
1909 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001910 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911 break;
1912 default:
vivek mehtadae44712015-07-27 14:13:18 -07001913 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914 return -EINVAL;
1915 }
1916
1917 return 0;
1918}
1919
vivek mehtaa68fea62017-06-08 19:04:02 -07001920static size_t get_stream_buffer_size(size_t duration_ms,
1921 uint32_t sample_rate,
1922 audio_format_t format,
1923 int channel_count,
1924 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925{
1926 size_t size = 0;
1927
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001928 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1929 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930
vivek mehtaa68fea62017-06-08 19:04:02 -07001931 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001932 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001933 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001934
1935 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936
Glenn Kasten4f993392014-05-14 07:30:48 -07001937 /* make sure the size is multiple of 32 bytes
1938 * At 48 kHz mono 16-bit PCM:
1939 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1940 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1941 */
1942 size += 0x1f;
1943 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001944
1945 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946}
1947
1948static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1949{
1950 struct stream_out *out = (struct stream_out *)stream;
1951
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001952 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953}
1954
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001955static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956{
1957 return -ENOSYS;
1958}
1959
1960static size_t out_get_buffer_size(const struct audio_stream *stream)
1961{
1962 struct stream_out *out = (struct stream_out *)stream;
1963
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001964 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1965 return out->compr_config.fragment_size;
1966 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001967 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001968 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969}
1970
1971static uint32_t out_get_channels(const struct audio_stream *stream)
1972{
1973 struct stream_out *out = (struct stream_out *)stream;
1974
1975 return out->channel_mask;
1976}
1977
1978static audio_format_t out_get_format(const struct audio_stream *stream)
1979{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001980 struct stream_out *out = (struct stream_out *)stream;
1981
1982 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983}
1984
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001985static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986{
1987 return -ENOSYS;
1988}
1989
1990static int out_standby(struct audio_stream *stream)
1991{
1992 struct stream_out *out = (struct stream_out *)stream;
1993 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001994 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001995
Eric Laurent994a6932013-07-17 11:51:42 -07001996 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001997 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998
Eric Laurenta1478072015-09-21 17:21:52 -07001999 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002001 if (adev->adm_deregister_stream)
2002 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002003 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002005 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2006 if (out->pcm) {
2007 pcm_close(out->pcm);
2008 out->pcm = NULL;
2009 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002010 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002011 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002012 out->playback_started = false;
2013 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002014 } else {
2015 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002016 out->gapless_mdata.encoder_delay = 0;
2017 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002018 if (out->compr != NULL) {
2019 compress_close(out->compr);
2020 out->compr = NULL;
2021 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002022 }
Phil Burkbc991042017-02-24 08:06:44 -08002023 if (do_stop) {
2024 stop_output_stream(out);
2025 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002026 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027 }
2028 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002029 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 return 0;
2031}
2032
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002033static int out_on_error(struct audio_stream *stream)
2034{
2035 struct stream_out *out = (struct stream_out *)stream;
2036 struct audio_device *adev = out->dev;
2037 bool do_standby = false;
2038
2039 lock_output_stream(out);
2040 if (!out->standby) {
2041 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2042 stop_compressed_output_l(out);
2043 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2044 } else
2045 do_standby = true;
2046 }
2047 pthread_mutex_unlock(&out->lock);
2048
2049 if (do_standby)
2050 return out_standby(&out->stream.common);
2051
2052 return 0;
2053}
2054
Andy Hung7401c7c2016-09-21 12:41:21 -07002055static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056{
Andy Hung7401c7c2016-09-21 12:41:21 -07002057 struct stream_out *out = (struct stream_out *)stream;
2058
2059 // We try to get the lock for consistency,
2060 // but it isn't necessary for these variables.
2061 // If we're not in standby, we may be blocked on a write.
2062 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2063 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2064 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2065
2066 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002067 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002068 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002069
2070 // dump error info
2071 (void)error_log_dump(
2072 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002073 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002074 (void)power_log_dump(
2075 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 return 0;
2077}
2078
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002079static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2080{
2081 int ret = 0;
2082 char value[32];
2083 struct compr_gapless_mdata tmp_mdata;
2084
2085 if (!out || !parms) {
2086 return -EINVAL;
2087 }
2088
2089 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2090 if (ret >= 0) {
2091 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2092 } else {
2093 return -EINVAL;
2094 }
2095
2096 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2097 if (ret >= 0) {
2098 tmp_mdata.encoder_padding = atoi(value);
2099 } else {
2100 return -EINVAL;
2101 }
2102
2103 out->gapless_mdata = tmp_mdata;
2104 out->send_new_metadata = 1;
2105 ALOGV("%s new encoder delay %u and padding %u", __func__,
2106 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2107
2108 return 0;
2109}
2110
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002111static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2112{
2113 return out == adev->primary_output || out == adev->voice_tx_output;
2114}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2117{
2118 struct stream_out *out = (struct stream_out *)stream;
2119 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002120 struct audio_usecase *usecase;
2121 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 struct str_parms *parms;
2123 char value[32];
2124 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002125 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002126 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127
Eric Laurent2e140aa2016-06-30 17:14:46 -07002128 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002129 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 parms = str_parms_create_str(kvpairs);
2131 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2132 if (ret >= 0) {
2133 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002134 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002135 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002137 /*
2138 * When HDMI cable is unplugged the music playback is paused and
2139 * the policy manager sends routing=0. But the audioflinger
2140 * continues to write data until standby time (3sec).
2141 * As the HDMI core is turned off, the write gets blocked.
2142 * Avoid this by routing audio to speaker until standby.
2143 */
2144 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2145 val == AUDIO_DEVICE_NONE) {
2146 val = AUDIO_DEVICE_OUT_SPEAKER;
2147 }
2148
2149 /*
2150 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002151 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002152 * the select_devices(). But how do we undo this?
2153 *
2154 * For example, music playback is active on headset (deep-buffer usecase)
2155 * and if we go to ringtones and select a ringtone, low-latency usecase
2156 * will be started on headset+speaker. As we can't enable headset+speaker
2157 * and headset devices at the same time, select_devices() switches the music
2158 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2159 * So when the ringtone playback is completed, how do we undo the same?
2160 *
2161 * We are relying on the out_set_parameters() call on deep-buffer output,
2162 * once the ringtone playback is ended.
2163 * NOTE: We should not check if the current devices are same as new devices.
2164 * Because select_devices() must be called to switch back the music
2165 * playback to headset.
2166 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002167 audio_devices_t new_dev = val;
2168 if (new_dev != AUDIO_DEVICE_NONE) {
2169 bool same_dev = out->devices == new_dev;
2170 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002171
Eric Laurenta7657192014-10-09 21:09:33 -07002172 if (output_drives_call(adev, out)) {
2173 if (!voice_is_in_call(adev)) {
2174 if (adev->mode == AUDIO_MODE_IN_CALL) {
2175 adev->current_call_output = out;
2176 ret = voice_start_call(adev);
2177 }
2178 } else {
2179 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002180 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002181 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002182 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002183
2184 if (!out->standby) {
2185 if (!same_dev) {
2186 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002187 // inform adm before actual routing to prevent glitches.
2188 if (adev->adm_on_routing_change) {
2189 adev->adm_on_routing_change(adev->adm_data,
2190 out->handle);
2191 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002192 }
2193 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002194 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002195 }
2196
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002197 }
2198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002200 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002201
2202 /*handles device and call state changes*/
2203 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002205
2206 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2207 parse_compress_metadata(out, parms);
2208 }
2209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002211 ALOGV("%s: exit: code(%d)", __func__, status);
2212 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213}
2214
Haynes Mathew George569b7482017-05-08 14:44:27 -07002215static bool stream_get_parameter_channels(struct str_parms *query,
2216 struct str_parms *reply,
2217 audio_channel_mask_t *supported_channel_masks) {
2218 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002221 size_t i, j;
2222
2223 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2224 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 value[0] = '\0';
2226 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002227 while (supported_channel_masks[i] != 0) {
2228 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2229 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 if (!first) {
2231 strcat(value, "|");
2232 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002233 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 first = false;
2235 break;
2236 }
2237 }
2238 i++;
2239 }
2240 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002241 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002242 return ret >= 0;
2243}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002244
Haynes Mathew George569b7482017-05-08 14:44:27 -07002245static bool stream_get_parameter_formats(struct str_parms *query,
2246 struct str_parms *reply,
2247 audio_format_t *supported_formats) {
2248 int ret = -1;
2249 char value[256];
2250 int i;
2251
2252 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2253 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002254 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002255 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002256 case AUDIO_FORMAT_PCM_16_BIT:
2257 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2258 break;
2259 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2260 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2261 break;
2262 case AUDIO_FORMAT_PCM_32_BIT:
2263 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2264 break;
2265 default:
2266 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002267 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002268 break;
2269 }
2270 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002271 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002272 return ret >= 0;
2273}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002274
Haynes Mathew George569b7482017-05-08 14:44:27 -07002275static bool stream_get_parameter_rates(struct str_parms *query,
2276 struct str_parms *reply,
2277 uint32_t *supported_sample_rates) {
2278
2279 int i;
2280 char value[256];
2281 int ret = -1;
2282 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2283 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002284 value[0] = '\0';
2285 i=0;
2286 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002287 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002288 int avail = sizeof(value) - cursor;
2289 ret = snprintf(value + cursor, avail, "%s%d",
2290 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002291 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002292 if (ret < 0 || ret >= avail) {
2293 // if cursor is at the last element of the array
2294 // overwrite with \0 is duplicate work as
2295 // snprintf already put a \0 in place.
2296 // else
2297 // we had space to write the '|' at value[cursor]
2298 // (which will be overwritten) or no space to fill
2299 // the first element (=> cursor == 0)
2300 value[cursor] = '\0';
2301 break;
2302 }
2303 cursor += ret;
2304 ++i;
2305 }
2306 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2307 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002308 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002309 return ret >= 0;
2310}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002311
Haynes Mathew George569b7482017-05-08 14:44:27 -07002312static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2313{
2314 struct stream_out *out = (struct stream_out *)stream;
2315 struct str_parms *query = str_parms_create_str(keys);
2316 char *str;
2317 struct str_parms *reply = str_parms_create();
2318 bool replied = false;
2319 ALOGV("%s: enter: keys - %s", __func__, keys);
2320
2321 replied |= stream_get_parameter_channels(query, reply,
2322 &out->supported_channel_masks[0]);
2323 replied |= stream_get_parameter_formats(query, reply,
2324 &out->supported_formats[0]);
2325 replied |= stream_get_parameter_rates(query, reply,
2326 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002327 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328 str = str_parms_to_str(reply);
2329 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002330 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 }
2332 str_parms_destroy(query);
2333 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002334 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 return str;
2336}
2337
2338static uint32_t out_get_latency(const struct audio_stream_out *stream)
2339{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002340 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 struct stream_out *out = (struct stream_out *)stream;
2342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2344 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002345 else if ((out->realtime) ||
2346 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002347 // since the buffer won't be filled up faster than realtime,
2348 // return a smaller number
2349 period_ms = (out->af_period_multiplier * out->config.period_size *
2350 1000) / (out->config.rate);
2351 hw_delay = platform_render_latency(out->usecase)/1000;
2352 return period_ms + hw_delay;
2353 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354
2355 return (out->config.period_count * out->config.period_size * 1000) /
2356 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357}
2358
2359static int out_set_volume(struct audio_stream_out *stream, float left,
2360 float right)
2361{
Eric Laurenta9024de2013-04-04 09:19:12 -07002362 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 int volume[2];
2364
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002365 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002366 /* only take left channel into account: the API is for stereo anyway */
2367 out->muted = (left == 0.0f);
2368 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2370 const char *mixer_ctl_name = "Compress Playback Volume";
2371 struct audio_device *adev = out->dev;
2372 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2374 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002375 /* try with the control based on device id */
2376 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2377 PCM_PLAYBACK);
2378 char ctl_name[128] = {0};
2379 snprintf(ctl_name, sizeof(ctl_name),
2380 "Compress Playback %d Volume", pcm_device_id);
2381 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2382 if (!ctl) {
2383 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2384 return -EINVAL;
2385 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 }
2387 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2388 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2389 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2390 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002391 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002392 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2393 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2394 if (!out->standby) {
2395 // if in standby, cached volume will be sent after stream is opened
2396 audio_extn_utils_send_app_type_gain(out->dev,
2397 out->app_type_cfg.app_type,
2398 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002399 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002400 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002401 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403 return -ENOSYS;
2404}
2405
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002406// note: this call is safe only if the stream_cb is
2407// removed first in close_output_stream (as is done now).
2408static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2409{
2410 if (!stream || !parms)
2411 return;
2412
2413 struct stream_out *out = (struct stream_out *)stream;
2414 struct audio_device *adev = out->dev;
2415
2416 card_status_t status;
2417 int card;
2418 if (parse_snd_card_status(parms, &card, &status) < 0)
2419 return;
2420
2421 pthread_mutex_lock(&adev->lock);
2422 bool valid_cb = (card == adev->snd_card);
2423 pthread_mutex_unlock(&adev->lock);
2424
2425 if (!valid_cb)
2426 return;
2427
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002428 lock_output_stream(out);
2429 if (out->card_status != status)
2430 out->card_status = status;
2431 pthread_mutex_unlock(&out->lock);
2432
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002433 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2434 use_case_table[out->usecase],
2435 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2436
2437 if (status == CARD_STATUS_OFFLINE)
2438 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002439
2440 return;
2441}
2442
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002443#ifdef NO_AUDIO_OUT
2444static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002445 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002446{
2447 struct stream_out *out = (struct stream_out *)stream;
2448
2449 /* No Output device supported other than BT for playback.
2450 * Sleep for the amount of buffer duration
2451 */
Eric Laurenta1478072015-09-21 17:21:52 -07002452 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002453 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2454 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002455 out_get_sample_rate(&out->stream.common));
2456 pthread_mutex_unlock(&out->lock);
2457 return bytes;
2458}
2459#endif
2460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2462 size_t bytes)
2463{
2464 struct stream_out *out = (struct stream_out *)stream;
2465 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002466 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002467 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468
Eric Laurenta1478072015-09-21 17:21:52 -07002469 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002470 // this is always nonzero
2471 const int frame_size = audio_stream_out_frame_size(stream);
2472
Eric Laurent0e46adf2016-12-16 12:49:24 -08002473 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2474 error_code = ERROR_CODE_WRITE;
2475 goto exit;
2476 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002478 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002479 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002481 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002482 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002484 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 goto exit;
2486 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002487
2488 if (last_known_cal_step != -1) {
2489 ALOGD("%s: retry previous failed cal level set", __func__);
2490 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002494 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002495 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002496 if (out->send_new_metadata) {
2497 ALOGVV("send new gapless metadata");
2498 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2499 out->send_new_metadata = 0;
2500 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002501 unsigned int avail;
2502 struct timespec tstamp;
2503 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2504 /* Do not limit write size if the available frames count is unknown */
2505 if (ret != 0) {
2506 avail = bytes;
2507 }
2508 if (avail == 0) {
2509 ret = 0;
2510 } else {
2511 if (avail > bytes) {
2512 avail = bytes;
2513 }
2514 ret = compress_write(out->compr, buffer, avail);
2515 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2516 __func__, avail, ret);
2517 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002518
Eric Laurent6e895242013-09-05 16:10:57 -07002519 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002520 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2521 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002522 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002523 compress_start(out->compr);
2524 out->playback_started = 1;
2525 out->offload_state = OFFLOAD_STATE_PLAYING;
2526 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002527 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002528 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002529 } else {
2530 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002531 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002532 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002533 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534 return ret;
2535 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002536 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002537 if (out->pcm) {
2538 if (out->muted)
2539 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002540
Eric Laurent0e46adf2016-12-16 12:49:24 -08002541 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002542
Haynes Mathew George03c40102016-01-29 17:57:48 -08002543 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2544 out->config.rate;
2545 request_out_focus(out, ns);
2546
2547 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2548 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002549 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002550 else
2551 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002552
Haynes Mathew George03c40102016-01-29 17:57:48 -08002553 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002554 } else {
2555 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557 }
2558
2559exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002560 // For PCM we always consume the buffer and return #bytes regardless of ret.
2561 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2562 out->written += bytes / (out->config.channels * sizeof(short));
2563 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002564 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002565
2566 // only get time if needed for logging, as it is a system call on 32 bit devices.
2567 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2568 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2569 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002570
Andy Hung7401c7c2016-09-21 12:41:21 -07002571 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002572 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002573 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2574 ALOGE_IF(out->pcm != NULL,
2575 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002576 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002577 out_get_sample_rate(&out->stream.common);
2578 // usleep not guaranteed for values over 1 second but we don't limit here.
2579 }
2580 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 pthread_mutex_unlock(&out->lock);
2583
2584 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002585 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002586 if (sleeptime_us != 0)
2587 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002588 } else {
2589 // only log if the data is properly written (out->power_log may be null)
2590 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 }
2592 return bytes;
2593}
2594
2595static int out_get_render_position(const struct audio_stream_out *stream,
2596 uint32_t *dsp_frames)
2597{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 struct stream_out *out = (struct stream_out *)stream;
2599 *dsp_frames = 0;
2600 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002601 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002602 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002603 unsigned long frames = 0;
2604 // TODO: check return value
2605 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2606 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002607 ALOGVV("%s rendered frames %d sample_rate %d",
2608 __func__, *dsp_frames, out->sample_rate);
2609 }
2610 pthread_mutex_unlock(&out->lock);
2611 return 0;
2612 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002613 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614}
2615
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002616static int out_add_audio_effect(const struct audio_stream *stream __unused,
2617 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618{
2619 return 0;
2620}
2621
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002622static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2623 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624{
2625 return 0;
2626}
2627
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002628static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2629 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002631 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632}
2633
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002634static int out_get_presentation_position(const struct audio_stream_out *stream,
2635 uint64_t *frames, struct timespec *timestamp)
2636{
2637 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002638 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002639 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002640
Eric Laurenta1478072015-09-21 17:21:52 -07002641 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002642
Eric Laurent949a0892013-09-20 09:20:13 -07002643 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2644 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002645 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002646 compress_get_tstamp(out->compr, &dsp_frames,
2647 &out->sample_rate);
2648 ALOGVV("%s rendered frames %ld sample_rate %d",
2649 __func__, dsp_frames, out->sample_rate);
2650 *frames = dsp_frames;
2651 ret = 0;
2652 /* this is the best we can do */
2653 clock_gettime(CLOCK_MONOTONIC, timestamp);
2654 }
2655 } else {
2656 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002657 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002658 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2659 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002660 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002661 // This adjustment accounts for buffering after app processor.
2662 // It is based on estimated DSP latency per use case, rather than exact.
2663 signed_frames -=
2664 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2665
Eric Laurent949a0892013-09-20 09:20:13 -07002666 // It would be unusual for this value to be negative, but check just in case ...
2667 if (signed_frames >= 0) {
2668 *frames = signed_frames;
2669 ret = 0;
2670 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002671 }
2672 }
2673 }
2674
2675 pthread_mutex_unlock(&out->lock);
2676
2677 return ret;
2678}
2679
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002680static int out_set_callback(struct audio_stream_out *stream,
2681 stream_callback_t callback, void *cookie)
2682{
2683 struct stream_out *out = (struct stream_out *)stream;
2684
2685 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002686 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002687 out->offload_callback = callback;
2688 out->offload_cookie = cookie;
2689 pthread_mutex_unlock(&out->lock);
2690 return 0;
2691}
2692
2693static int out_pause(struct audio_stream_out* stream)
2694{
2695 struct stream_out *out = (struct stream_out *)stream;
2696 int status = -ENOSYS;
2697 ALOGV("%s", __func__);
2698 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002699 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002700 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2701 status = compress_pause(out->compr);
2702 out->offload_state = OFFLOAD_STATE_PAUSED;
2703 }
2704 pthread_mutex_unlock(&out->lock);
2705 }
2706 return status;
2707}
2708
2709static int out_resume(struct audio_stream_out* stream)
2710{
2711 struct stream_out *out = (struct stream_out *)stream;
2712 int status = -ENOSYS;
2713 ALOGV("%s", __func__);
2714 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2715 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002716 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002717 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2718 status = compress_resume(out->compr);
2719 out->offload_state = OFFLOAD_STATE_PLAYING;
2720 }
2721 pthread_mutex_unlock(&out->lock);
2722 }
2723 return status;
2724}
2725
2726static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2727{
2728 struct stream_out *out = (struct stream_out *)stream;
2729 int status = -ENOSYS;
2730 ALOGV("%s", __func__);
2731 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002732 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002733 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2734 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2735 else
2736 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2737 pthread_mutex_unlock(&out->lock);
2738 }
2739 return status;
2740}
2741
2742static int out_flush(struct audio_stream_out* stream)
2743{
2744 struct stream_out *out = (struct stream_out *)stream;
2745 ALOGV("%s", __func__);
2746 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002747 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002748 stop_compressed_output_l(out);
2749 pthread_mutex_unlock(&out->lock);
2750 return 0;
2751 }
2752 return -ENOSYS;
2753}
2754
Eric Laurent0e46adf2016-12-16 12:49:24 -08002755static int out_stop(const struct audio_stream_out* stream)
2756{
2757 struct stream_out *out = (struct stream_out *)stream;
2758 struct audio_device *adev = out->dev;
2759 int ret = -ENOSYS;
2760
2761 ALOGV("%s", __func__);
2762 pthread_mutex_lock(&adev->lock);
2763 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2764 out->playback_started && out->pcm != NULL) {
2765 pcm_stop(out->pcm);
2766 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002767 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002768 }
2769 pthread_mutex_unlock(&adev->lock);
2770 return ret;
2771}
2772
2773static int out_start(const struct audio_stream_out* stream)
2774{
2775 struct stream_out *out = (struct stream_out *)stream;
2776 struct audio_device *adev = out->dev;
2777 int ret = -ENOSYS;
2778
2779 ALOGV("%s", __func__);
2780 pthread_mutex_lock(&adev->lock);
2781 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2782 !out->playback_started && out->pcm != NULL) {
2783 ret = start_output_stream(out);
2784 if (ret == 0) {
2785 out->playback_started = true;
2786 }
2787 }
2788 pthread_mutex_unlock(&adev->lock);
2789 return ret;
2790}
2791
Phil Burkbc991042017-02-24 08:06:44 -08002792/*
2793 * Modify config->period_count based on min_size_frames
2794 */
2795static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2796{
2797 int periodCountRequested = (min_size_frames + config->period_size - 1)
2798 / config->period_size;
2799 int periodCount = MMAP_PERIOD_COUNT_MIN;
2800
2801 ALOGV("%s original config.period_size = %d config.period_count = %d",
2802 __func__, config->period_size, config->period_count);
2803
2804 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2805 periodCount *= 2;
2806 }
2807 config->period_count = periodCount;
2808
2809 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2810}
2811
Eric Laurent0e46adf2016-12-16 12:49:24 -08002812static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2813 int32_t min_size_frames,
2814 struct audio_mmap_buffer_info *info)
2815{
2816 struct stream_out *out = (struct stream_out *)stream;
2817 struct audio_device *adev = out->dev;
2818 int ret = 0;
2819 unsigned int offset1;
2820 unsigned int frames1;
2821 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002822 uint32_t mmap_size;
2823 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002824
2825 ALOGV("%s", __func__);
2826 pthread_mutex_lock(&adev->lock);
2827
2828 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002829 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002830 ret = -EINVAL;
2831 goto exit;
2832 }
2833 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002834 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002835 ret = -ENOSYS;
2836 goto exit;
2837 }
2838 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2839 if (out->pcm_device_id < 0) {
2840 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2841 __func__, out->pcm_device_id, out->usecase);
2842 ret = -EINVAL;
2843 goto exit;
2844 }
Phil Burkbc991042017-02-24 08:06:44 -08002845
2846 adjust_mmap_period_count(&out->config, min_size_frames);
2847
Eric Laurent0e46adf2016-12-16 12:49:24 -08002848 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2849 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2850 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2851 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2852 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2853 step = "open";
2854 ret = -ENODEV;
2855 goto exit;
2856 }
2857 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2858 if (ret < 0) {
2859 step = "begin";
2860 goto exit;
2861 }
2862 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002863 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002864 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002865 ret = platform_get_mmap_data_fd(adev->platform,
2866 out->pcm_device_id, 0 /*playback*/,
2867 &info->shared_memory_fd,
2868 &mmap_size);
2869 if (ret < 0) {
2870 // Fall back to non exclusive mode
2871 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2872 } else {
2873 if (mmap_size < buffer_size) {
2874 step = "mmap";
2875 goto exit;
2876 }
2877 // FIXME: indicate exclusive mode support by returning a negative buffer size
2878 info->buffer_size_frames *= -1;
2879 }
2880 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002881
2882 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2883 if (ret < 0) {
2884 step = "commit";
2885 goto exit;
2886 }
Phil Burkbc991042017-02-24 08:06:44 -08002887
2888 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002889 ret = 0;
2890
2891 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2892 __func__, info->shared_memory_address, info->buffer_size_frames);
2893
2894exit:
2895 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002896 if (out->pcm == NULL) {
2897 ALOGE("%s: %s - %d", __func__, step, ret);
2898 } else {
2899 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002900 pcm_close(out->pcm);
2901 out->pcm = NULL;
2902 }
2903 }
2904 pthread_mutex_unlock(&adev->lock);
2905 return ret;
2906}
2907
2908static int out_get_mmap_position(const struct audio_stream_out *stream,
2909 struct audio_mmap_position *position)
2910{
2911 struct stream_out *out = (struct stream_out *)stream;
2912 ALOGVV("%s", __func__);
2913 if (position == NULL) {
2914 return -EINVAL;
2915 }
2916 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2917 return -ENOSYS;
2918 }
2919 if (out->pcm == NULL) {
2920 return -ENOSYS;
2921 }
2922
2923 struct timespec ts = { 0, 0 };
2924 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2925 if (ret < 0) {
2926 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2927 return ret;
2928 }
Andy Hungfc044e12017-03-20 09:24:22 -07002929 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002930 return 0;
2931}
2932
2933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934/** audio_stream_in implementation **/
2935static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2936{
2937 struct stream_in *in = (struct stream_in *)stream;
2938
2939 return in->config.rate;
2940}
2941
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002942static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943{
2944 return -ENOSYS;
2945}
2946
2947static size_t in_get_buffer_size(const struct audio_stream *stream)
2948{
2949 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002950 return in->config.period_size * in->af_period_multiplier *
2951 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002952}
2953
2954static uint32_t in_get_channels(const struct audio_stream *stream)
2955{
2956 struct stream_in *in = (struct stream_in *)stream;
2957
2958 return in->channel_mask;
2959}
2960
vivek mehta4ed66e62016-04-15 23:33:34 -07002961static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962{
vivek mehta4ed66e62016-04-15 23:33:34 -07002963 struct stream_in *in = (struct stream_in *)stream;
2964 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002965}
2966
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002967static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968{
2969 return -ENOSYS;
2970}
2971
2972static int in_standby(struct audio_stream *stream)
2973{
2974 struct stream_in *in = (struct stream_in *)stream;
2975 struct audio_device *adev = in->dev;
2976 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002977 bool do_stop = true;
2978
Eric Laurent994a6932013-07-17 11:51:42 -07002979 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002980
2981 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002982
2983 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002984 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002985 audio_extn_sound_trigger_stop_lab(in);
2986 in->standby = true;
2987 }
2988
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002990 if (adev->adm_deregister_stream)
2991 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2992
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002993 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002995 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002996 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002997 in->capture_started = false;
2998 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002999 if (in->pcm) {
3000 pcm_close(in->pcm);
3001 in->pcm = NULL;
3002 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003003 adev->enable_voicerx = false;
3004 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003005 if (do_stop) {
3006 status = stop_input_stream(in);
3007 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003008 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 }
3010 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003011 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012 return status;
3013}
3014
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003015static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016{
3017 return 0;
3018}
3019
3020static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3021{
3022 struct stream_in *in = (struct stream_in *)stream;
3023 struct audio_device *adev = in->dev;
3024 struct str_parms *parms;
3025 char *str;
3026 char value[32];
3027 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003028 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029
Eric Laurent994a6932013-07-17 11:51:42 -07003030 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031 parms = str_parms_create_str(kvpairs);
3032
3033 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3034
Eric Laurenta1478072015-09-21 17:21:52 -07003035 lock_input_stream(in);
3036
Eric Laurent150dbfe2013-02-27 14:31:02 -08003037 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003038 if (ret >= 0) {
3039 val = atoi(value);
3040 /* no audio source uses val == 0 */
3041 if ((in->source != val) && (val != 0)) {
3042 in->source = val;
3043 }
3044 }
3045
3046 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003047
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003048 if (ret >= 0) {
3049 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003050 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 in->device = val;
3052 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003053 if (!in->standby) {
3054 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003055 // inform adm before actual routing to prevent glitches.
3056 if (adev->adm_on_routing_change) {
3057 adev->adm_on_routing_change(adev->adm_data,
3058 in->capture_handle);
3059 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003060 select_devices(adev, in->usecase);
3061 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062 }
3063 }
3064
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003066 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003067
3068 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003069 ALOGV("%s: exit: status(%d)", __func__, status);
3070 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071}
3072
Haynes Mathew George569b7482017-05-08 14:44:27 -07003073static char* in_get_parameters(const struct audio_stream *stream,
3074 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003076 struct stream_in *in = (struct stream_in *)stream;
3077 struct str_parms *query = str_parms_create_str(keys);
3078 char *str;
3079 struct str_parms *reply = str_parms_create();
3080 bool replied = false;
3081
3082 ALOGV("%s: enter: keys - %s", __func__, keys);
3083 replied |= stream_get_parameter_channels(query, reply,
3084 &in->supported_channel_masks[0]);
3085 replied |= stream_get_parameter_formats(query, reply,
3086 &in->supported_formats[0]);
3087 replied |= stream_get_parameter_rates(query, reply,
3088 &in->supported_sample_rates[0]);
3089 if (replied) {
3090 str = str_parms_to_str(reply);
3091 } else {
3092 str = strdup(keys);
3093 }
3094 str_parms_destroy(query);
3095 str_parms_destroy(reply);
3096 ALOGV("%s: exit: returns - %s", __func__, str);
3097 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098}
3099
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003100static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003101{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003102 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103}
3104
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003105static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3106{
3107 if (!stream || !parms)
3108 return;
3109
3110 struct stream_in *in = (struct stream_in *)stream;
3111 struct audio_device *adev = in->dev;
3112
3113 card_status_t status;
3114 int card;
3115 if (parse_snd_card_status(parms, &card, &status) < 0)
3116 return;
3117
3118 pthread_mutex_lock(&adev->lock);
3119 bool valid_cb = (card == adev->snd_card);
3120 pthread_mutex_unlock(&adev->lock);
3121
3122 if (!valid_cb)
3123 return;
3124
3125 lock_input_stream(in);
3126 if (in->card_status != status)
3127 in->card_status = status;
3128 pthread_mutex_unlock(&in->lock);
3129
3130 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3131 use_case_table[in->usecase],
3132 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3133
3134 // a better solution would be to report error back to AF and let
3135 // it put the stream to standby
3136 if (status == CARD_STATUS_OFFLINE)
3137 in_standby(&in->stream.common);
3138
3139 return;
3140}
3141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3143 size_t bytes)
3144{
3145 struct stream_in *in = (struct stream_in *)stream;
3146 struct audio_device *adev = in->dev;
3147 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003148 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149
Eric Laurenta1478072015-09-21 17:21:52 -07003150 lock_input_stream(in);
3151
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003152 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003153 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003154 /* Read from sound trigger HAL */
3155 audio_extn_sound_trigger_read(in, buffer, bytes);
3156 pthread_mutex_unlock(&in->lock);
3157 return bytes;
3158 }
3159
Eric Laurent0e46adf2016-12-16 12:49:24 -08003160 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3161 ret = -ENOSYS;
3162 goto exit;
3163 }
3164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003166 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003168 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170 goto exit;
3171 }
3172 in->standby = 0;
3173 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174
Haynes Mathew George03c40102016-01-29 17:57:48 -08003175 //what's the duration requested by the client?
3176 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3177 in->config.rate;
3178 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003179
Haynes Mathew George03c40102016-01-29 17:57:48 -08003180 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003182 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003183 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003184 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003185 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003186 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003187 if (ret < 0) {
3188 ALOGE("Failed to read w/err %s", strerror(errno));
3189 ret = -errno;
3190 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003191 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3192 if (bytes % 4 == 0) {
3193 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3194 int_buf_stream = buffer;
3195 for (size_t itt=0; itt < bytes/4 ; itt++) {
3196 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003197 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003198 } else {
3199 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3200 ret = -EINVAL;
3201 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003202 }
3203 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003204 }
3205
Haynes Mathew George03c40102016-01-29 17:57:48 -08003206 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003208 /*
3209 * Instead of writing zeroes here, we could trust the hardware
3210 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003211 * 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 -08003212 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003213 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003214 memset(buffer, 0, bytes);
3215
3216exit:
3217 pthread_mutex_unlock(&in->lock);
3218
3219 if (ret != 0) {
3220 in_standby(&in->stream.common);
3221 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07003222 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003224 memset(buffer, 0, bytes); // clear return data
3225 }
3226 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08003227 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228 }
3229 return bytes;
3230}
3231
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003232static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233{
3234 return 0;
3235}
3236
Andy Hung6ebe5962016-01-15 17:46:57 -08003237static int in_get_capture_position(const struct audio_stream_in *stream,
3238 int64_t *frames, int64_t *time)
3239{
3240 if (stream == NULL || frames == NULL || time == NULL) {
3241 return -EINVAL;
3242 }
3243 struct stream_in *in = (struct stream_in *)stream;
3244 int ret = -ENOSYS;
3245
3246 lock_input_stream(in);
3247 if (in->pcm) {
3248 struct timespec timestamp;
3249 unsigned int avail;
3250 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3251 *frames = in->frames_read + avail;
3252 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3253 ret = 0;
3254 }
3255 }
3256 pthread_mutex_unlock(&in->lock);
3257 return ret;
3258}
3259
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003260static int add_remove_audio_effect(const struct audio_stream *stream,
3261 effect_handle_t effect,
3262 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003263{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003264 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003265 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003266 int status = 0;
3267 effect_descriptor_t desc;
3268
3269 status = (*effect)->get_descriptor(effect, &desc);
3270 if (status != 0)
3271 return status;
3272
Eric Laurenta1478072015-09-21 17:21:52 -07003273 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003274 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003275 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003276 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003277 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003278 in->enable_aec != enable &&
3279 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3280 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003281 if (!enable)
3282 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003283 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3284 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3285 adev->enable_voicerx = enable;
3286 struct audio_usecase *usecase;
3287 struct listnode *node;
3288 list_for_each(node, &adev->usecase_list) {
3289 usecase = node_to_item(node, struct audio_usecase, list);
3290 if (usecase->type == PCM_PLAYBACK) {
3291 select_devices(adev, usecase->id);
3292 break;
3293 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003294 }
3295 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003296 if (!in->standby)
3297 select_devices(in->dev, in->usecase);
3298 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003299 if (in->enable_ns != enable &&
3300 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3301 in->enable_ns = enable;
3302 if (!in->standby)
3303 select_devices(in->dev, in->usecase);
3304 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003305 pthread_mutex_unlock(&in->dev->lock);
3306 pthread_mutex_unlock(&in->lock);
3307
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308 return 0;
3309}
3310
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003311static int in_add_audio_effect(const struct audio_stream *stream,
3312 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313{
Eric Laurent994a6932013-07-17 11:51:42 -07003314 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003315 return add_remove_audio_effect(stream, effect, true);
3316}
3317
3318static int in_remove_audio_effect(const struct audio_stream *stream,
3319 effect_handle_t effect)
3320{
Eric Laurent994a6932013-07-17 11:51:42 -07003321 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003322 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323}
3324
Eric Laurent0e46adf2016-12-16 12:49:24 -08003325static int in_stop(const struct audio_stream_in* stream)
3326{
3327 struct stream_in *in = (struct stream_in *)stream;
3328 struct audio_device *adev = in->dev;
3329
3330 int ret = -ENOSYS;
3331 ALOGV("%s", __func__);
3332 pthread_mutex_lock(&adev->lock);
3333 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3334 in->capture_started && in->pcm != NULL) {
3335 pcm_stop(in->pcm);
3336 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003337 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003338 }
3339 pthread_mutex_unlock(&adev->lock);
3340 return ret;
3341}
3342
3343static int in_start(const struct audio_stream_in* stream)
3344{
3345 struct stream_in *in = (struct stream_in *)stream;
3346 struct audio_device *adev = in->dev;
3347 int ret = -ENOSYS;
3348
3349 ALOGV("%s in %p", __func__, in);
3350 pthread_mutex_lock(&adev->lock);
3351 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3352 !in->capture_started && in->pcm != NULL) {
3353 if (!in->capture_started) {
3354 ret = start_input_stream(in);
3355 if (ret == 0) {
3356 in->capture_started = true;
3357 }
3358 }
3359 }
3360 pthread_mutex_unlock(&adev->lock);
3361 return ret;
3362}
3363
3364static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3365 int32_t min_size_frames,
3366 struct audio_mmap_buffer_info *info)
3367{
3368 struct stream_in *in = (struct stream_in *)stream;
3369 struct audio_device *adev = in->dev;
3370 int ret = 0;
3371 unsigned int offset1;
3372 unsigned int frames1;
3373 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003374 uint32_t mmap_size;
3375 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003376
3377 pthread_mutex_lock(&adev->lock);
3378 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003379
Eric Laurent0e46adf2016-12-16 12:49:24 -08003380 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003381 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003382 ret = -EINVAL;
3383 goto exit;
3384 }
3385 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003386 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003387 ALOGV("%s in %p", __func__, in);
3388 ret = -ENOSYS;
3389 goto exit;
3390 }
3391 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3392 if (in->pcm_device_id < 0) {
3393 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3394 __func__, in->pcm_device_id, in->usecase);
3395 ret = -EINVAL;
3396 goto exit;
3397 }
Phil Burkbc991042017-02-24 08:06:44 -08003398
3399 adjust_mmap_period_count(&in->config, min_size_frames);
3400
Eric Laurent0e46adf2016-12-16 12:49:24 -08003401 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3402 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3403 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3404 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3405 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3406 step = "open";
3407 ret = -ENODEV;
3408 goto exit;
3409 }
3410
3411 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3412 if (ret < 0) {
3413 step = "begin";
3414 goto exit;
3415 }
3416 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003417 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003418 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003419 ret = platform_get_mmap_data_fd(adev->platform,
3420 in->pcm_device_id, 1 /*capture*/,
3421 &info->shared_memory_fd,
3422 &mmap_size);
3423 if (ret < 0) {
3424 // Fall back to non exclusive mode
3425 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3426 } else {
3427 if (mmap_size < buffer_size) {
3428 step = "mmap";
3429 goto exit;
3430 }
3431 // FIXME: indicate exclusive mode support by returning a negative buffer size
3432 info->buffer_size_frames *= -1;
3433 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003434
Haynes Mathew George96483a22017-03-28 14:52:47 -07003435 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003436
3437 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3438 if (ret < 0) {
3439 step = "commit";
3440 goto exit;
3441 }
3442
Phil Burkbc991042017-02-24 08:06:44 -08003443 in->standby = false;
3444 ret = 0;
3445
Eric Laurent0e46adf2016-12-16 12:49:24 -08003446 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3447 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003448
3449exit:
3450 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003451 if (in->pcm == NULL) {
3452 ALOGE("%s: %s - %d", __func__, step, ret);
3453 } else {
3454 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003455 pcm_close(in->pcm);
3456 in->pcm = NULL;
3457 }
3458 }
3459 pthread_mutex_unlock(&adev->lock);
3460 return ret;
3461}
3462
3463static int in_get_mmap_position(const struct audio_stream_in *stream,
3464 struct audio_mmap_position *position)
3465{
3466 struct stream_in *in = (struct stream_in *)stream;
3467 ALOGVV("%s", __func__);
3468 if (position == NULL) {
3469 return -EINVAL;
3470 }
3471 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3472 return -ENOSYS;
3473 }
3474 if (in->pcm == NULL) {
3475 return -ENOSYS;
3476 }
3477 struct timespec ts = { 0, 0 };
3478 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3479 if (ret < 0) {
3480 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3481 return ret;
3482 }
Andy Hungfc044e12017-03-20 09:24:22 -07003483 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003484 return 0;
3485}
3486
3487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488static int adev_open_output_stream(struct audio_hw_device *dev,
3489 audio_io_handle_t handle,
3490 audio_devices_t devices,
3491 audio_output_flags_t flags,
3492 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003493 struct audio_stream_out **stream_out,
3494 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003495{
3496 struct audio_device *adev = (struct audio_device *)dev;
3497 struct stream_out *out;
3498 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003499 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3500 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3501 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3502 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503
Eric Laurent994a6932013-07-17 11:51:42 -07003504 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505 __func__, config->sample_rate, config->channel_mask, devices, flags);
3506 *stream_out = NULL;
3507 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3508
3509 if (devices == AUDIO_DEVICE_NONE)
3510 devices = AUDIO_DEVICE_OUT_SPEAKER;
3511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512 out->flags = flags;
3513 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003514 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003515 out->format = config->format;
3516 out->sample_rate = config->sample_rate;
3517 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3518 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003519 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520
3521 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003522 if (audio_is_linear_pcm(out->format) &&
3523 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003524 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003525 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003526 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003527 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003528 if (config->sample_rate == 0)
3529 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3530 if (config->channel_mask == 0)
3531 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3532 if (config->format == AUDIO_FORMAT_DEFAULT)
3533 config->format = AUDIO_FORMAT_PCM_16_BIT;
3534 } else if (is_usb_dev) {
3535 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3536 &config->format,
3537 &out->supported_formats[0],
3538 MAX_SUPPORTED_FORMATS,
3539 &config->channel_mask,
3540 &out->supported_channel_masks[0],
3541 MAX_SUPPORTED_CHANNEL_MASKS,
3542 &config->sample_rate,
3543 &out->supported_sample_rates[0],
3544 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003545 ALOGV("plugged dev USB ret %d", ret);
3546 } else {
3547 ret = -1;
3548 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003549 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003550 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003551 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003552
Haynes Mathew George569b7482017-05-08 14:44:27 -07003553 out->channel_mask = config->channel_mask;
3554 out->sample_rate = config->sample_rate;
3555 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003556 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3557 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003558 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003559 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003560 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003562 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003563 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003564 pthread_mutex_lock(&adev->lock);
3565 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3566 pthread_mutex_unlock(&adev->lock);
3567
3568 // reject offload during card offline to allow
3569 // fallback to s/w paths
3570 if (offline) {
3571 ret = -ENODEV;
3572 goto error_open;
3573 }
3574
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003575 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3576 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3577 ALOGE("%s: Unsupported Offload information", __func__);
3578 ret = -EINVAL;
3579 goto error_open;
3580 }
3581 if (!is_supported_format(config->offload_info.format)) {
3582 ALOGE("%s: Unsupported audio format", __func__);
3583 ret = -EINVAL;
3584 goto error_open;
3585 }
3586
3587 out->compr_config.codec = (struct snd_codec *)
3588 calloc(1, sizeof(struct snd_codec));
3589
3590 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3591 if (config->offload_info.channel_mask)
3592 out->channel_mask = config->offload_info.channel_mask;
3593 else if (config->channel_mask)
3594 out->channel_mask = config->channel_mask;
3595 out->format = config->offload_info.format;
3596 out->sample_rate = config->offload_info.sample_rate;
3597
3598 out->stream.set_callback = out_set_callback;
3599 out->stream.pause = out_pause;
3600 out->stream.resume = out_resume;
3601 out->stream.drain = out_drain;
3602 out->stream.flush = out_flush;
3603
3604 out->compr_config.codec->id =
3605 get_snd_codec_id(config->offload_info.format);
3606 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3607 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003608 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003609 out->compr_config.codec->bit_rate =
3610 config->offload_info.bit_rate;
3611 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003612 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003613 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3614
3615 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3616 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003617
3618 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003619 create_offload_callback_thread(out);
3620 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3621 __func__, config->offload_info.version,
3622 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003623 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003624 switch (config->sample_rate) {
3625 case 8000:
3626 case 16000:
3627 case 48000:
3628 out->sample_rate = config->sample_rate;
3629 break;
3630 default:
3631 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003632 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003633 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003634 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3635 out->config = pcm_config_afe_proxy_playback;
3636 adev->voice_tx_output = out;
vivek mehtaa68fea62017-06-08 19:04:02 -07003637 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3638 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3639 AUDIO_OUTPUT_FLAG_VOIP_RX))) {
3640 uint32_t buffer_size, frame_size;
3641 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3642 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3643 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3644 out->config = pcm_config_voip;
3645 out->config.format = pcm_format_from_audio_format(config->format);
3646 out->config.rate = config->sample_rate;
3647 out->config.channels =
3648 audio_channel_count_from_out_mask(config->channel_mask);
3649 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3650 config->sample_rate,
3651 config->format,
3652 out->config.channels,
3653 false /*is_low_latency*/);
3654 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3655 out->config.period_size = buffer_size / frame_size;
3656 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3657 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003659 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3660 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3661 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003662 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3663 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3664 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003665 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3666 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003667 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003668 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003669 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3670 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3671 out->config = pcm_config_mmap_playback;
3672 out->stream.start = out_start;
3673 out->stream.stop = out_stop;
3674 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3675 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003676 } else {
3677 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3678 out->config = pcm_config_low_latency;
3679 }
3680 if (config->format != audio_format_from_pcm_format(out->config.format)) {
Haynes Mathew Georgedf0f8862017-06-28 13:36:40 -07003681 out->config.format = pcm_format_from_audio_format(config->format);
Andy Hung6fcba9c2014-03-18 11:53:32 -07003682 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003683 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003685
3686 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3687 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3688 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3689 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3690 __func__, config->sample_rate, config->format, config->channel_mask);
3691 config->sample_rate = out->sample_rate;
3692 config->format = out->format;
3693 config->channel_mask = out->channel_mask;
3694 ret = -EINVAL;
3695 goto error_open;
3696 }
3697
Andy Hung6fcba9c2014-03-18 11:53:32 -07003698 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3699 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003700
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003701 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003702 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003703 adev->primary_output = out;
3704 else {
3705 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003706 ret = -EEXIST;
3707 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003708 }
3709 }
3710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003711 /* Check if this usecase is already existing */
3712 pthread_mutex_lock(&adev->lock);
3713 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3714 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003716 ret = -EEXIST;
3717 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718 }
3719 pthread_mutex_unlock(&adev->lock);
3720
3721 out->stream.common.get_sample_rate = out_get_sample_rate;
3722 out->stream.common.set_sample_rate = out_set_sample_rate;
3723 out->stream.common.get_buffer_size = out_get_buffer_size;
3724 out->stream.common.get_channels = out_get_channels;
3725 out->stream.common.get_format = out_get_format;
3726 out->stream.common.set_format = out_set_format;
3727 out->stream.common.standby = out_standby;
3728 out->stream.common.dump = out_dump;
3729 out->stream.common.set_parameters = out_set_parameters;
3730 out->stream.common.get_parameters = out_get_parameters;
3731 out->stream.common.add_audio_effect = out_add_audio_effect;
3732 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3733 out->stream.get_latency = out_get_latency;
3734 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003735#ifdef NO_AUDIO_OUT
3736 out->stream.write = out_write_for_no_output;
3737#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003739#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003740 out->stream.get_render_position = out_get_render_position;
3741 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003742 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743
Eric Laurent0e46adf2016-12-16 12:49:24 -08003744 if (out->realtime)
3745 out->af_period_multiplier = af_period_multiplier;
3746 else
3747 out->af_period_multiplier = 1;
3748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003750 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003751 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003753 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003754 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003755 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 config->format = out->stream.common.get_format(&out->stream.common);
3758 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3759 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3760
Andy Hunga452b0a2017-03-15 14:51:15 -07003761 out->error_log = error_log_create(
3762 ERROR_LOG_ENTRIES,
3763 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3764
Andy Hungfc044e12017-03-20 09:24:22 -07003765 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003766 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003767 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003768 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3769 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3770
3771 out->power_log = power_log_create(
3772 config->sample_rate,
3773 audio_channel_count_from_out_mask(config->channel_mask),
3774 config->format,
3775 POWER_LOG_ENTRIES,
3776 POWER_LOG_FRAMES_PER_ENTRY);
3777 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003778
3779 /*
3780 By locking output stream before registering, we allow the callback
3781 to update stream's state only after stream's initial state is set to
3782 adev state.
3783 */
3784 lock_output_stream(out);
3785 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3786 pthread_mutex_lock(&adev->lock);
3787 out->card_status = adev->card_status;
3788 pthread_mutex_unlock(&adev->lock);
3789 pthread_mutex_unlock(&out->lock);
3790
vivek mehta4a824772017-06-08 19:05:49 -07003791 stream_app_type_cfg_init(&out->app_type_cfg);
3792
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003794
Eric Laurent994a6932013-07-17 11:51:42 -07003795 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003797
3798error_open:
3799 free(out);
3800 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003801 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003802 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803}
3804
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003805static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806 struct audio_stream_out *stream)
3807{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003808 struct stream_out *out = (struct stream_out *)stream;
3809 struct audio_device *adev = out->dev;
3810
Eric Laurent994a6932013-07-17 11:51:42 -07003811 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003812
3813 // must deregister from sndmonitor first to prevent races
3814 // between the callback and close_stream
3815 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003817 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3818 destroy_offload_callback_thread(out);
3819
3820 if (out->compr_config.codec != NULL)
3821 free(out->compr_config.codec);
3822 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003823
3824 if (adev->voice_tx_output == out)
3825 adev->voice_tx_output = NULL;
3826
Andy Hungfc044e12017-03-20 09:24:22 -07003827 power_log_destroy(out->power_log);
3828 out->power_log = NULL;
3829
Andy Hunga452b0a2017-03-15 14:51:15 -07003830 error_log_destroy(out->error_log);
3831 out->error_log = NULL;
3832
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003833 pthread_cond_destroy(&out->cond);
3834 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003836 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837}
3838
3839static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3840{
3841 struct audio_device *adev = (struct audio_device *)dev;
3842 struct str_parms *parms;
3843 char *str;
3844 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003845 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003847 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848
Joe Onorato188b6222016-03-01 11:02:27 -08003849 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003850
3851 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003852
3853 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003854 status = voice_set_parameters(adev, parms);
3855 if (status != 0) {
3856 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857 }
3858
3859 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3860 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003861 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3863 adev->bluetooth_nrec = true;
3864 else
3865 adev->bluetooth_nrec = false;
3866 }
3867
3868 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3869 if (ret >= 0) {
3870 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3871 adev->screen_off = false;
3872 else
3873 adev->screen_off = true;
3874 }
3875
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003876 ret = str_parms_get_int(parms, "rotation", &val);
3877 if (ret >= 0) {
3878 bool reverse_speakers = false;
3879 switch(val) {
3880 // FIXME: note that the code below assumes that the speakers are in the correct placement
3881 // relative to the user when the device is rotated 90deg from its default rotation. This
3882 // assumption is device-specific, not platform-specific like this code.
3883 case 270:
3884 reverse_speakers = true;
3885 break;
3886 case 0:
3887 case 90:
3888 case 180:
3889 break;
3890 default:
3891 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003892 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003893 }
Eric Laurent03f09432014-03-25 18:09:11 -07003894 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003895 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003896 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003897 }
3898
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003899 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3900 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003901 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003902 }
3903
David Linee3fe402017-03-13 10:00:42 -07003904 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3905 if (ret >= 0) {
3906 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003907 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003908 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3909 if (ret >= 0) {
3910 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003911 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003912 }
Eric Laurent99dab492017-06-17 15:19:08 -07003913 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003914 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3915 if (ret >= 0) {
3916 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003917 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003918 }
3919 }
3920 }
3921
3922 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3923 if (ret >= 0) {
3924 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003925 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003926 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3927 if (ret >= 0) {
3928 const int card = atoi(value);
3929
Eric Laurent99dab492017-06-17 15:19:08 -07003930 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003931 }
Eric Laurent99dab492017-06-17 15:19:08 -07003932 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003933 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3934 if (ret >= 0) {
3935 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003936 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003937 }
3938 }
3939 }
3940
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003941 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003942done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003944 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003945 ALOGV("%s: exit with code(%d)", __func__, status);
3946 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003947}
3948
3949static char* adev_get_parameters(const struct audio_hw_device *dev,
3950 const char *keys)
3951{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003952 struct audio_device *adev = (struct audio_device *)dev;
3953 struct str_parms *reply = str_parms_create();
3954 struct str_parms *query = str_parms_create_str(keys);
3955 char *str;
3956
3957 pthread_mutex_lock(&adev->lock);
3958
3959 voice_get_parameters(adev, query, reply);
3960 str = str_parms_to_str(reply);
3961 str_parms_destroy(query);
3962 str_parms_destroy(reply);
3963
3964 pthread_mutex_unlock(&adev->lock);
3965 ALOGV("%s: exit: returns - %s", __func__, str);
3966 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003967}
3968
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003969static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970{
3971 return 0;
3972}
3973
Haynes Mathew George5191a852013-09-11 14:19:36 -07003974static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3975{
3976 int ret;
3977 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003978
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003979 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3980
Haynes Mathew George5191a852013-09-11 14:19:36 -07003981 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003982 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003983 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003984
Haynes Mathew George5191a852013-09-11 14:19:36 -07003985 return ret;
3986}
3987
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003988static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989{
3990 return -ENOSYS;
3991}
3992
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003993static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3994 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003995{
3996 return -ENOSYS;
3997}
3998
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003999static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004000{
4001 return -ENOSYS;
4002}
4003
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004004static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005{
4006 return -ENOSYS;
4007}
4008
4009static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4010{
4011 struct audio_device *adev = (struct audio_device *)dev;
4012
4013 pthread_mutex_lock(&adev->lock);
4014 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004015 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004016 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004017 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4018 voice_is_in_call(adev)) {
4019 voice_stop_call(adev);
4020 adev->current_call_output = NULL;
4021 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004022 }
4023 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004024
4025 audio_extn_extspk_set_mode(adev->extspk, mode);
4026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004027 return 0;
4028}
4029
4030static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4031{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004032 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004033 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004034
Eric Laurent2bafff12016-03-17 12:17:23 -07004035 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004036 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004037 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4038 ret = audio_extn_hfp_set_mic_mute(adev, state);
4039 } else {
4040 ret = voice_set_mic_mute(adev, state);
4041 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004042 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004043 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004044
4045 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046}
4047
4048static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4049{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004050 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051 return 0;
4052}
4053
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004054static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055 const struct audio_config *config)
4056{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004057 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058
vivek mehtaa68fea62017-06-08 19:04:02 -07004059 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4060 config->sample_rate, config->format,
4061 channel_count,
4062 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004063}
4064
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004065static bool adev_input_allow_hifi_record(struct audio_device *adev,
4066 audio_devices_t devices,
4067 audio_input_flags_t flags,
4068 audio_source_t source) {
4069 const bool allowed = true;
4070
4071 if (!audio_is_usb_in_device(devices))
4072 return !allowed;
4073
4074 switch (flags) {
4075 case AUDIO_INPUT_FLAG_NONE:
4076 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4077 break;
4078 default:
4079 return !allowed;
4080 }
4081
4082 switch (source) {
4083 case AUDIO_SOURCE_DEFAULT:
4084 case AUDIO_SOURCE_MIC:
4085 case AUDIO_SOURCE_UNPROCESSED:
4086 break;
4087 default:
4088 return !allowed;
4089 }
4090
4091 switch (adev->mode) {
4092 case 0:
4093 break;
4094 default:
4095 return !allowed;
4096 }
4097
4098 return allowed;
4099}
4100
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004101static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004102 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103 audio_devices_t devices,
4104 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004105 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004106 audio_input_flags_t flags,
4107 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004108 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004109{
4110 struct audio_device *adev = (struct audio_device *)dev;
4111 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004112 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004113 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004114 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004115 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004116 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4117 devices,
4118 flags,
4119 source);
4120 ALOGE("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004122
4123 if (config->sample_rate == 0)
4124 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4125 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4126 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4127 if (config->format == AUDIO_FORMAT_DEFAULT)
4128 config->format = AUDIO_FORMAT_PCM_16_BIT;
4129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
4131 return -EINVAL;
4132
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004133 if (audio_extn_tfa_98xx_is_supported() &&
4134 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004135 return -EINVAL;
4136
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4138
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004139 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004140 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004141
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142 in->stream.common.get_sample_rate = in_get_sample_rate;
4143 in->stream.common.set_sample_rate = in_set_sample_rate;
4144 in->stream.common.get_buffer_size = in_get_buffer_size;
4145 in->stream.common.get_channels = in_get_channels;
4146 in->stream.common.get_format = in_get_format;
4147 in->stream.common.set_format = in_set_format;
4148 in->stream.common.standby = in_standby;
4149 in->stream.common.dump = in_dump;
4150 in->stream.common.set_parameters = in_set_parameters;
4151 in->stream.common.get_parameters = in_get_parameters;
4152 in->stream.common.add_audio_effect = in_add_audio_effect;
4153 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4154 in->stream.set_gain = in_set_gain;
4155 in->stream.read = in_read;
4156 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004157 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004158
4159 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004160 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 in->standby = 1;
4163 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004164 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004165 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004166
Haynes Mathew George569b7482017-05-08 14:44:27 -07004167 if (is_usb_dev && may_use_hifi_record) {
4168 /* HiFi record selects an appropriate format, channel, rate combo
4169 depending on sink capabilities*/
4170 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4171 &config->format,
4172 &in->supported_formats[0],
4173 MAX_SUPPORTED_FORMATS,
4174 &config->channel_mask,
4175 &in->supported_channel_masks[0],
4176 MAX_SUPPORTED_CHANNEL_MASKS,
4177 &config->sample_rate,
4178 &in->supported_sample_rates[0],
4179 MAX_SUPPORTED_SAMPLE_RATES);
4180 if (ret != 0) {
4181 ret = -EINVAL;
4182 goto err_open;
4183 }
4184 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004185 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004186 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4187 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4188 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4189 bool ret_error = false;
4190 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4191 from HAL is 8_24
4192 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4193 8_24 return error indicating supported format is 8_24
4194 *> In case of any other source requesting 24 bit or float return error
4195 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004196
vivek mehta57ff9b52016-04-28 14:13:08 -07004197 on error flinger will retry with supported format passed
4198 */
4199 if (source != AUDIO_SOURCE_UNPROCESSED) {
4200 config->format = AUDIO_FORMAT_PCM_16_BIT;
4201 ret_error = true;
4202 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4203 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4204 ret_error = true;
4205 }
4206
4207 if (ret_error) {
4208 ret = -EINVAL;
4209 goto err_open;
4210 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004211 }
4212
vivek mehta57ff9b52016-04-28 14:13:08 -07004213 in->format = config->format;
4214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004216 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4217 if (config->sample_rate == 0)
4218 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4219 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4220 config->sample_rate != 8000) {
4221 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4222 ret = -EINVAL;
4223 goto err_open;
4224 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004225
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004226 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4227 config->format = AUDIO_FORMAT_PCM_16_BIT;
4228 ret = -EINVAL;
4229 goto err_open;
4230 }
4231
4232 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4233 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004234 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004235 } else if (is_usb_dev && may_use_hifi_record) {
4236 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4237 in->config = pcm_config_audio_capture;
4238 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004239 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4240 config->sample_rate,
4241 config->format,
4242 channel_count,
4243 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004244 in->config.period_size = buffer_size / frame_size;
4245 in->config.rate = config->sample_rate;
4246 in->af_period_multiplier = 1;
4247 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004248 } else {
4249 in->usecase = USECASE_AUDIO_RECORD;
4250 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004251 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004252 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004253#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004254 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004255#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004256 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004257 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004258 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004259 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004260 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4261 config->sample_rate,
4262 config->format,
4263 channel_count,
4264 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004265 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004266 in->config.rate = config->sample_rate;
4267 in->af_period_multiplier = 1;
4268 } else {
4269 // period size is left untouched for rt mode playback
4270 in->config = pcm_config_audio_capture_rt;
4271 in->af_period_multiplier = af_period_multiplier;
4272 }
4273 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4274 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004275 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004276 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4277 in->config = pcm_config_mmap_capture;
4278 in->stream.start = in_start;
4279 in->stream.stop = in_stop;
4280 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4281 in->stream.get_mmap_position = in_get_mmap_position;
4282 in->af_period_multiplier = 1;
4283 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004284 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
4285 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004286 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004287 (config->sample_rate == 8000 ||
4288 config->sample_rate == 16000 ||
4289 config->sample_rate == 32000 ||
4290 config->sample_rate == 48000) &&
4291 channel_count == 1) {
4292 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4293 in->config = pcm_config_audio_capture;
4294 frame_size = audio_stream_in_frame_size(&in->stream);
4295 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4296 config->sample_rate,
4297 config->format,
4298 channel_count, false /*is_low_latency*/);
4299 in->config.period_size = buffer_size / frame_size;
4300 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4301 in->config.rate = config->sample_rate;
4302 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004303 } else {
4304 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004305 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004306 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4307 config->sample_rate,
4308 config->format,
4309 channel_count,
4310 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004311 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004312 in->config.rate = config->sample_rate;
4313 in->af_period_multiplier = 1;
4314 }
4315 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4316 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004317 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004319 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004320 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004322 /* This stream could be for sound trigger lab,
4323 get sound trigger pcm if present */
4324 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004326 lock_input_stream(in);
4327 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4328 pthread_mutex_lock(&adev->lock);
4329 in->card_status = adev->card_status;
4330 pthread_mutex_unlock(&adev->lock);
4331 pthread_mutex_unlock(&in->lock);
4332
vivek mehta4a824772017-06-08 19:05:49 -07004333 stream_app_type_cfg_init(&in->app_type_cfg);
4334
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004335 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004336 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004337 return 0;
4338
4339err_open:
4340 free(in);
4341 *stream_in = NULL;
4342 return ret;
4343}
4344
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004345static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004346 struct audio_stream_in *stream)
4347{
Eric Laurent994a6932013-07-17 11:51:42 -07004348 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004349
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004350 // must deregister from sndmonitor first to prevent races
4351 // between the callback and close_stream
4352 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353 in_standby(&stream->common);
4354 free(stream);
4355
4356 return;
4357}
4358
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004359static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360{
4361 return 0;
4362}
4363
Andy Hung31aca912014-03-20 17:14:59 -07004364/* verifies input and output devices and their capabilities.
4365 *
4366 * This verification is required when enabling extended bit-depth or
4367 * sampling rates, as not all qcom products support it.
4368 *
4369 * Suitable for calling only on initialization such as adev_open().
4370 * It fills the audio_device use_case_table[] array.
4371 *
4372 * Has a side-effect that it needs to configure audio routing / devices
4373 * in order to power up the devices and read the device parameters.
4374 * It does not acquire any hw device lock. Should restore the devices
4375 * back to "normal state" upon completion.
4376 */
4377static int adev_verify_devices(struct audio_device *adev)
4378{
4379 /* enumeration is a bit difficult because one really wants to pull
4380 * the use_case, device id, etc from the hidden pcm_device_table[].
4381 * In this case there are the following use cases and device ids.
4382 *
4383 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4384 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004385 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004386 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4387 * [USECASE_AUDIO_RECORD] = {0, 0},
4388 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4389 * [USECASE_VOICE_CALL] = {2, 2},
4390 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004391 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004392 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4393 */
4394
4395 /* should be the usecases enabled in adev_open_input_stream() */
4396 static const int test_in_usecases[] = {
4397 USECASE_AUDIO_RECORD,
4398 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4399 };
4400 /* should be the usecases enabled in adev_open_output_stream()*/
4401 static const int test_out_usecases[] = {
4402 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4403 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4404 };
4405 static const usecase_type_t usecase_type_by_dir[] = {
4406 PCM_PLAYBACK,
4407 PCM_CAPTURE,
4408 };
4409 static const unsigned flags_by_dir[] = {
4410 PCM_OUT,
4411 PCM_IN,
4412 };
4413
4414 size_t i;
4415 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004416 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004417 char info[512]; /* for possible debug info */
4418
4419 for (dir = 0; dir < 2; ++dir) {
4420 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4421 const unsigned flags_dir = flags_by_dir[dir];
4422 const size_t testsize =
4423 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4424 const int *testcases =
4425 dir ? test_in_usecases : test_out_usecases;
4426 const audio_devices_t audio_device =
4427 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4428
4429 for (i = 0; i < testsize; ++i) {
4430 const audio_usecase_t audio_usecase = testcases[i];
4431 int device_id;
4432 snd_device_t snd_device;
4433 struct pcm_params **pparams;
4434 struct stream_out out;
4435 struct stream_in in;
4436 struct audio_usecase uc_info;
4437 int retval;
4438
4439 pparams = &adev->use_case_table[audio_usecase];
4440 pcm_params_free(*pparams); /* can accept null input */
4441 *pparams = NULL;
4442
4443 /* find the device ID for the use case (signed, for error) */
4444 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4445 if (device_id < 0)
4446 continue;
4447
4448 /* prepare structures for device probing */
4449 memset(&uc_info, 0, sizeof(uc_info));
4450 uc_info.id = audio_usecase;
4451 uc_info.type = usecase_type;
4452 if (dir) {
4453 adev->active_input = &in;
4454 memset(&in, 0, sizeof(in));
4455 in.device = audio_device;
4456 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4457 uc_info.stream.in = &in;
4458 } else {
4459 adev->active_input = NULL;
4460 }
4461 memset(&out, 0, sizeof(out));
4462 out.devices = audio_device; /* only field needed in select_devices */
4463 uc_info.stream.out = &out;
4464 uc_info.devices = audio_device;
4465 uc_info.in_snd_device = SND_DEVICE_NONE;
4466 uc_info.out_snd_device = SND_DEVICE_NONE;
4467 list_add_tail(&adev->usecase_list, &uc_info.list);
4468
4469 /* select device - similar to start_(in/out)put_stream() */
4470 retval = select_devices(adev, audio_usecase);
4471 if (retval >= 0) {
4472 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4473#if LOG_NDEBUG == 0
4474 if (*pparams) {
4475 ALOGV("%s: (%s) card %d device %d", __func__,
4476 dir ? "input" : "output", card_id, device_id);
4477 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004478 } else {
4479 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4480 }
4481#endif
4482 }
4483
4484 /* deselect device - similar to stop_(in/out)put_stream() */
4485 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004486 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004487 /* 2. Disable the rx device */
4488 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004489 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004490 list_remove(&uc_info.list);
4491 }
4492 }
4493 adev->active_input = NULL; /* restore adev state */
4494 return 0;
4495}
4496
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004497static int adev_close(hw_device_t *device)
4498{
Andy Hung31aca912014-03-20 17:14:59 -07004499 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004501
4502 if (!adev)
4503 return 0;
4504
4505 pthread_mutex_lock(&adev_init_lock);
4506
4507 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004508 audio_extn_snd_mon_unregister_listener(adev);
4509 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004510 audio_route_free(adev->audio_route);
4511 free(adev->snd_dev_ref_cnt);
4512 platform_deinit(adev->platform);
4513 audio_extn_extspk_deinit(adev->extspk);
4514 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004515 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004516 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4517 pcm_params_free(adev->use_case_table[i]);
4518 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004519 if (adev->adm_deinit)
4520 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004521 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004522 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004523
4524 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004525
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004526 return 0;
4527}
4528
Glenn Kasten4f993392014-05-14 07:30:48 -07004529/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4530 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4531 * just that it _might_ work.
4532 */
4533static int period_size_is_plausible_for_low_latency(int period_size)
4534{
4535 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004536 case 48:
4537 case 96:
4538 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004539 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004540 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004541 case 240:
4542 case 320:
4543 case 480:
4544 return 1;
4545 default:
4546 return 0;
4547 }
4548}
4549
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004550static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4551{
4552 int card;
4553 card_status_t status;
4554
4555 if (!parms)
4556 return;
4557
4558 if (parse_snd_card_status(parms, &card, &status) < 0)
4559 return;
4560
4561 pthread_mutex_lock(&adev->lock);
4562 bool valid_cb = (card == adev->snd_card);
4563 if (valid_cb) {
4564 if (adev->card_status != status) {
4565 adev->card_status = status;
4566 platform_snd_card_update(adev->platform, status);
4567 }
4568 }
4569 pthread_mutex_unlock(&adev->lock);
4570 return;
4571}
4572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004573static int adev_open(const hw_module_t *module, const char *name,
4574 hw_device_t **device)
4575{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004576 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004577
Eric Laurent2bafff12016-03-17 12:17:23 -07004578 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004580 pthread_mutex_lock(&adev_init_lock);
4581 if (audio_device_ref_count != 0) {
4582 *device = &adev->device.common;
4583 audio_device_ref_count++;
4584 ALOGV("%s: returning existing instance of adev", __func__);
4585 ALOGV("%s: exit", __func__);
4586 pthread_mutex_unlock(&adev_init_lock);
4587 return 0;
4588 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589 adev = calloc(1, sizeof(struct audio_device));
4590
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004591 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4594 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4595 adev->device.common.module = (struct hw_module_t *)module;
4596 adev->device.common.close = adev_close;
4597
4598 adev->device.init_check = adev_init_check;
4599 adev->device.set_voice_volume = adev_set_voice_volume;
4600 adev->device.set_master_volume = adev_set_master_volume;
4601 adev->device.get_master_volume = adev_get_master_volume;
4602 adev->device.set_master_mute = adev_set_master_mute;
4603 adev->device.get_master_mute = adev_get_master_mute;
4604 adev->device.set_mode = adev_set_mode;
4605 adev->device.set_mic_mute = adev_set_mic_mute;
4606 adev->device.get_mic_mute = adev_get_mic_mute;
4607 adev->device.set_parameters = adev_set_parameters;
4608 adev->device.get_parameters = adev_get_parameters;
4609 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4610 adev->device.open_output_stream = adev_open_output_stream;
4611 adev->device.close_output_stream = adev_close_output_stream;
4612 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614 adev->device.close_input_stream = adev_close_input_stream;
4615 adev->device.dump = adev_dump;
4616
4617 /* Set the default route before the PCM stream is opened */
4618 pthread_mutex_lock(&adev->lock);
4619 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004620 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004621 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004623 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004624 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004625 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004626 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004627 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004628 pthread_mutex_unlock(&adev->lock);
4629
4630 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004631 adev->platform = platform_init(adev);
4632 if (!adev->platform) {
4633 free(adev->snd_dev_ref_cnt);
4634 free(adev);
4635 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4636 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004637 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004638 return -EINVAL;
4639 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004640 adev->extspk = audio_extn_extspk_init(adev);
4641
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004642 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4643 if (adev->visualizer_lib == NULL) {
4644 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4645 } else {
4646 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4647 adev->visualizer_start_output =
4648 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4649 "visualizer_hal_start_output");
4650 adev->visualizer_stop_output =
4651 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4652 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004653 }
4654
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004655 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4656 if (adev->offload_effects_lib == NULL) {
4657 ALOGW("%s: DLOPEN failed for %s", __func__,
4658 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4659 } else {
4660 ALOGV("%s: DLOPEN successful for %s", __func__,
4661 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4662 adev->offload_effects_start_output =
4663 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4664 "offload_effects_bundle_hal_start_output");
4665 adev->offload_effects_stop_output =
4666 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4667 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004668 }
4669
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004670 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4671 if (adev->adm_lib == NULL) {
4672 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4673 } else {
4674 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4675 adev->adm_init = (adm_init_t)
4676 dlsym(adev->adm_lib, "adm_init");
4677 adev->adm_deinit = (adm_deinit_t)
4678 dlsym(adev->adm_lib, "adm_deinit");
4679 adev->adm_register_input_stream = (adm_register_input_stream_t)
4680 dlsym(adev->adm_lib, "adm_register_input_stream");
4681 adev->adm_register_output_stream = (adm_register_output_stream_t)
4682 dlsym(adev->adm_lib, "adm_register_output_stream");
4683 adev->adm_deregister_stream = (adm_deregister_stream_t)
4684 dlsym(adev->adm_lib, "adm_deregister_stream");
4685 adev->adm_request_focus = (adm_request_focus_t)
4686 dlsym(adev->adm_lib, "adm_request_focus");
4687 adev->adm_abandon_focus = (adm_abandon_focus_t)
4688 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004689 adev->adm_set_config = (adm_set_config_t)
4690 dlsym(adev->adm_lib, "adm_set_config");
4691 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4692 dlsym(adev->adm_lib, "adm_request_focus_v2");
4693 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4694 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4695 adev->adm_on_routing_change = (adm_on_routing_change_t)
4696 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004697 }
4698
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004699 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004700 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004702 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004703
Andy Hung31aca912014-03-20 17:14:59 -07004704 if (k_enable_extended_precision)
4705 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706
Glenn Kasten4f993392014-05-14 07:30:48 -07004707 char value[PROPERTY_VALUE_MAX];
4708 int trial;
4709 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4710 trial = atoi(value);
4711 if (period_size_is_plausible_for_low_latency(trial)) {
4712 pcm_config_low_latency.period_size = trial;
4713 pcm_config_low_latency.start_threshold = trial / 4;
4714 pcm_config_low_latency.avail_min = trial / 4;
4715 configured_low_latency_capture_period_size = trial;
4716 }
4717 }
4718 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4719 trial = atoi(value);
4720 if (period_size_is_plausible_for_low_latency(trial)) {
4721 configured_low_latency_capture_period_size = trial;
4722 }
4723 }
4724
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004725 // commented as full set of app type cfg is sent from platform
4726 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004727 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004728
4729 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4730 af_period_multiplier = atoi(value);
4731 if (af_period_multiplier < 0) {
4732 af_period_multiplier = 2;
4733 } else if (af_period_multiplier > 4) {
4734 af_period_multiplier = 4;
4735 }
4736 ALOGV("new period_multiplier = %d", af_period_multiplier);
4737 }
4738
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004739 audio_extn_tfa_98xx_init(adev);
4740
vivek mehta1a9b7c02015-06-25 11:49:38 -07004741 pthread_mutex_unlock(&adev_init_lock);
4742
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004743 if (adev->adm_init)
4744 adev->adm_data = adev->adm_init();
4745
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004746 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004747 audio_extn_snd_mon_init();
4748 pthread_mutex_lock(&adev->lock);
4749 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4750 adev->card_status = CARD_STATUS_ONLINE;
4751 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004752 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004753
Eric Laurent2bafff12016-03-17 12:17:23 -07004754 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004755 return 0;
4756}
4757
4758static struct hw_module_methods_t hal_module_methods = {
4759 .open = adev_open,
4760};
4761
4762struct audio_module HAL_MODULE_INFO_SYM = {
4763 .common = {
4764 .tag = HARDWARE_MODULE_TAG,
4765 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4766 .hal_api_version = HARDWARE_HAL_API_VERSION,
4767 .id = AUDIO_HARDWARE_MODULE_ID,
4768 .name = "QCOM Audio HAL",
4769 .author = "Code Aurora Forum",
4770 .methods = &hal_module_methods,
4771 },
4772};