blob: adaf44e43ab5366d8592559abede89ee03cf768d [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
Haynes Mathew Georgee6e2d442018-02-22 18:51:56 -080038#include <log/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080039#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040#include <cutils/str_parms.h>
41#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070042#include <cutils/atomic.h>
43#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080044
Eric Laurentb23d5282013-05-14 15:27:20 -070045#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070046#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070047#include <system/thread_defs.h>
Phil Burkbc991042017-02-24 08:06:44 -080048#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070049#include <audio_effects/effect_aec.h>
50#include <audio_effects/effect_ns.h>
Andy Hungfc044e12017-03-20 09:24:22 -070051#include <audio_utils/clock.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080052#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080053#include "audio_extn.h"
Wei Wangf4837d52017-11-21 14:51:20 -080054#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070076#define PROXY_OPEN_RETRY_COUNT 100
77#define PROXY_OPEN_WAIT_TIME 20
78
vivek mehtadae44712015-07-27 14:13:18 -070079#define MIN_CHANNEL_COUNT 1
80#define DEFAULT_CHANNEL_COUNT 2
81
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
83#define MAX_CHANNEL_COUNT 1
84#else
vivek mehtadae44712015-07-27 14:13:18 -070085#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
86#define XSTR(x) STR(x)
87#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#endif
Eric Laurent74b55762017-07-09 17:04:53 -070089#define MAX_HIFI_CHANNEL_COUNT 8
vivek mehtadae44712015-07-27 14:13:18 -070090
Haynes Mathew George03c40102016-01-29 17:57:48 -080091#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
92
Glenn Kasten4f993392014-05-14 07:30:48 -070093static unsigned int configured_low_latency_capture_period_size =
94 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
95
Eric Laurent0e46adf2016-12-16 12:49:24 -080096
97#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080098#define MMAP_PERIOD_COUNT_MIN 32
99#define MMAP_PERIOD_COUNT_MAX 512
100#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800101
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",
Nadav Bar3d72cfc2018-01-07 12:19:24 +0200288
289 [USECASE_INCALL_MUSIC_UPLINK] = "incall-music-uplink",
Eric Laurentb23d5282013-05-14 15:27:20 -0700290};
291
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800292
293#define STRING_TO_ENUM(string) { #string, string }
294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800295struct string_to_enum {
296 const char *name;
297 uint32_t value;
298};
299
Haynes Mathew George569b7482017-05-08 14:44:27 -0700300static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800301 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
302 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
303 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Eric Laurent74b55762017-07-09 17:04:53 -0700304 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700305 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
Eric Laurent74b55762017-07-09 17:04:53 -0700306 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
307 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
308 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
309 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
310 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
311 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
312 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
313 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
314 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800315};
316
Haynes Mathew George5191a852013-09-11 14:19:36 -0700317static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700318static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700319static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700320static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700321//cache last MBDRC cal step level
322static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700323
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800324static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
325static int set_compr_volume(struct audio_stream_out *stream, float left, float right);
326
Haynes Mathew George03c40102016-01-29 17:57:48 -0800327static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
328 int flags __unused)
329{
330 int dir = 0;
331 switch (uc_id) {
332 case USECASE_AUDIO_RECORD_LOW_LATENCY:
333 dir = 1;
334 case USECASE_AUDIO_PLAYBACK_ULL:
335 break;
336 default:
337 return false;
338 }
339
340 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
341 PCM_PLAYBACK : PCM_CAPTURE);
342 if (adev->adm_is_noirq_avail)
343 return adev->adm_is_noirq_avail(adev->adm_data,
344 adev->snd_card, dev_id, dir);
345 return false;
346}
347
348static void register_out_stream(struct stream_out *out)
349{
350 struct audio_device *adev = out->dev;
351 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
352 return;
353
354 if (!adev->adm_register_output_stream)
355 return;
356
357 adev->adm_register_output_stream(adev->adm_data,
358 out->handle,
359 out->flags);
360
361 if (!adev->adm_set_config)
362 return;
363
364 if (out->realtime) {
365 adev->adm_set_config(adev->adm_data,
366 out->handle,
367 out->pcm, &out->config);
368 }
369}
370
371static void register_in_stream(struct stream_in *in)
372{
373 struct audio_device *adev = in->dev;
374 if (!adev->adm_register_input_stream)
375 return;
376
377 adev->adm_register_input_stream(adev->adm_data,
378 in->capture_handle,
379 in->flags);
380
381 if (!adev->adm_set_config)
382 return;
383
384 if (in->realtime) {
385 adev->adm_set_config(adev->adm_data,
386 in->capture_handle,
387 in->pcm,
388 &in->config);
389 }
390}
391
392static void request_out_focus(struct stream_out *out, long ns)
393{
394 struct audio_device *adev = out->dev;
395
Haynes Mathew George03c40102016-01-29 17:57:48 -0800396 if (adev->adm_request_focus_v2) {
397 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
398 } else if (adev->adm_request_focus) {
399 adev->adm_request_focus(adev->adm_data, out->handle);
400 }
401}
402
403static void request_in_focus(struct stream_in *in, long ns)
404{
405 struct audio_device *adev = in->dev;
406
Haynes Mathew George03c40102016-01-29 17:57:48 -0800407 if (adev->adm_request_focus_v2) {
408 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
409 } else if (adev->adm_request_focus) {
410 adev->adm_request_focus(adev->adm_data, in->capture_handle);
411 }
412}
413
414static void release_out_focus(struct stream_out *out, long ns __unused)
415{
416 struct audio_device *adev = out->dev;
417
418 if (adev->adm_abandon_focus)
419 adev->adm_abandon_focus(adev->adm_data, out->handle);
420}
421
422static void release_in_focus(struct stream_in *in, long ns __unused)
423{
424 struct audio_device *adev = in->dev;
425 if (adev->adm_abandon_focus)
426 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
427}
428
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700429static int parse_snd_card_status(struct str_parms * parms, int * card,
430 card_status_t * status)
431{
432 char value[32]={0};
433 char state[32]={0};
434
435 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
436
437 if (ret < 0)
438 return -1;
439
440 // sscanf should be okay as value is of max length 32.
441 // same as sizeof state.
442 if (sscanf(value, "%d,%s", card, state) < 2)
443 return -1;
444
445 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
446 CARD_STATUS_OFFLINE;
447 return 0;
448}
449
vivek mehta40125092017-08-21 18:48:51 -0700450// always call with adev lock held
451void send_gain_dep_calibration_l() {
452 if (last_known_cal_step >= 0)
453 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
454}
455
vivek mehta1a9b7c02015-06-25 11:49:38 -0700456__attribute__ ((visibility ("default")))
457bool audio_hw_send_gain_dep_calibration(int level) {
458 bool ret_val = false;
459 ALOGV("%s: enter ... ", __func__);
460
461 pthread_mutex_lock(&adev_init_lock);
462
463 if (adev != NULL && adev->platform != NULL) {
464 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700465 last_known_cal_step = level;
466 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700467 pthread_mutex_unlock(&adev->lock);
468 } else {
469 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
470 }
471
472 pthread_mutex_unlock(&adev_init_lock);
473
474 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
475 return ret_val;
476}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700477
vivek mehtaa8d7c922016-05-25 14:40:44 -0700478__attribute__ ((visibility ("default")))
479int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
480 int table_size) {
481 int ret_val = 0;
482 ALOGV("%s: enter ... ", __func__);
483
484 pthread_mutex_lock(&adev_init_lock);
485 if (adev == NULL) {
486 ALOGW("%s: adev is NULL .... ", __func__);
487 goto done;
488 }
489
490 pthread_mutex_lock(&adev->lock);
491 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
492 pthread_mutex_unlock(&adev->lock);
493done:
494 pthread_mutex_unlock(&adev_init_lock);
495 ALOGV("%s: exit ... ", __func__);
496 return ret_val;
497}
498
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700499static bool is_supported_format(audio_format_t format)
500{
Eric Laurent8251ac82014-07-23 11:00:25 -0700501 switch (format) {
502 case AUDIO_FORMAT_MP3:
503 case AUDIO_FORMAT_AAC_LC:
504 case AUDIO_FORMAT_AAC_HE_V1:
505 case AUDIO_FORMAT_AAC_HE_V2:
506 return true;
507 default:
508 break;
509 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700510 return false;
511}
512
Haynes Mathew George03c40102016-01-29 17:57:48 -0800513static inline bool is_mmap_usecase(audio_usecase_t uc_id)
514{
515 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
516 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
517}
518
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700519static int get_snd_codec_id(audio_format_t format)
520{
521 int id = 0;
522
Eric Laurent8251ac82014-07-23 11:00:25 -0700523 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700524 case AUDIO_FORMAT_MP3:
525 id = SND_AUDIOCODEC_MP3;
526 break;
527 case AUDIO_FORMAT_AAC:
528 id = SND_AUDIOCODEC_AAC;
529 break;
530 default:
531 ALOGE("%s: Unsupported audio format", __func__);
532 }
533
534 return id;
535}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800536
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800537static int audio_ssr_status(struct audio_device *adev)
538{
539 int ret = 0;
540 struct mixer_ctl *ctl;
541 const char *mixer_ctl_name = "Audio SSR Status";
542
543 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
544 ret = mixer_ctl_get_value(ctl, 0);
545 ALOGD("%s: value: %d", __func__, ret);
546 return ret;
547}
548
vivek mehta4a824772017-06-08 19:05:49 -0700549static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
550{
551 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
552}
553
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800554static bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
555{
556 return out_snd_device == SND_DEVICE_OUT_BT_SCO ||
557 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
558 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
559 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
560 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
561 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC;
562
563}
564
565static bool is_a2dp_device(snd_device_t out_snd_device)
566{
567 return out_snd_device == SND_DEVICE_OUT_BT_A2DP;
568}
569
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800570int enable_audio_route(struct audio_device *adev,
571 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800572{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700573 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800575
576 if (usecase == NULL)
577 return -EINVAL;
578
579 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
580
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800581 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700582 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800583 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700584 snd_device = usecase->out_snd_device;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530585 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800586 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800587 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500588 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000589 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700590 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700591 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800593 ALOGV("%s: exit", __func__);
594 return 0;
595}
596
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800597int disable_audio_route(struct audio_device *adev,
598 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800599{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700600 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800601 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800602
603 if (usecase == NULL)
604 return -EINVAL;
605
606 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700607 if (usecase->type == PCM_CAPTURE)
608 snd_device = usecase->in_snd_device;
609 else
610 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800611 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500612 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700613 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700614 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000615 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800617 ALOGV("%s: exit", __func__);
618 return 0;
619}
620
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800621int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700622 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800623{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700624 int i, num_devices = 0;
625 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800626 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800627 if (snd_device < SND_DEVICE_MIN ||
628 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800629 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800630 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800631 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700632
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700633 platform_send_audio_calibration(adev->platform, snd_device);
634
vivek mehtade4849c2016-03-03 17:23:38 -0800635 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700636 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700637 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800638 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700639 }
640
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700641 /* due to the possibility of calibration overwrite between listen
642 and audio, notify sound trigger hal before audio calibration is sent */
643 audio_extn_sound_trigger_update_device_status(snd_device,
644 ST_EVENT_SND_DEVICE_BUSY);
645
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700646 if (audio_extn_spkr_prot_is_enabled())
647 audio_extn_spkr_prot_calib_cancel(adev);
648
zhaoyang yin4211fad2015-06-04 21:13:25 +0800649 audio_extn_dsm_feedback_enable(adev, snd_device, true);
650
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800651 if (is_a2dp_device(snd_device) &&
652 (audio_extn_a2dp_start_playback() < 0)) {
653 ALOGE("%s: failed to configure A2DP control path", __func__);
654 goto on_error;
655 }
656
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700657 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800658 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700659 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
660 audio_extn_spkr_prot_is_enabled()) {
661 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800662 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700663 }
664 if (audio_extn_spkr_prot_start_processing(snd_device)) {
665 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800666 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700667 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700668 } else if (platform_can_split_snd_device(snd_device,
669 &num_devices,
670 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700671 for (i = 0; i < num_devices; i++) {
672 enable_snd_device(adev, new_snd_devices[i]);
673 }
vivek mehtab6506412015-08-07 16:55:17 -0700674 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700675 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800676 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
677 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
678 ALOGE(" %s: Invalid sound device returned", __func__);
679 goto on_error;
680 }
Ed Tam70b5c142016-03-21 19:14:29 -0700681
Eric Laurent2e140aa2016-06-30 17:14:46 -0700682 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800683 audio_route_apply_and_update_path(adev->audio_route, device_name);
684 }
685on_success:
686 adev->snd_dev_ref_cnt[snd_device]++;
687 ret_val = 0;
688on_error:
689 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800690}
691
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800692int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700693 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800694{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700695 int i, num_devices = 0;
696 snd_device_t new_snd_devices[2];
697
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800698 if (snd_device < SND_DEVICE_MIN ||
699 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800700 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800701 return -EINVAL;
702 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
704 ALOGE("%s: device ref cnt is already 0", __func__);
705 return -EINVAL;
706 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800707 audio_extn_tfa_98xx_disable_speaker(snd_device);
708
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709 adev->snd_dev_ref_cnt[snd_device]--;
710 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800711 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800712
713 if (is_a2dp_device(snd_device))
714 audio_extn_a2dp_stop_playback();
715
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700716 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800717 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700718 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700719 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
720 audio_extn_spkr_prot_is_enabled()) {
721 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700722
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700723 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
724 // and does not use speaker swap. As this code causes a problem with device enable ref
725 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700726 // when speaker device is disabled, reset swap.
727 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700728 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700729
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700730 } else if (platform_can_split_snd_device(snd_device,
731 &num_devices,
732 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700733 for (i = 0; i < num_devices; i++) {
734 disable_snd_device(adev, new_snd_devices[i]);
735 }
vivek mehtab6506412015-08-07 16:55:17 -0700736 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700737 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800738 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
739 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
740 ALOGE(" %s: Invalid sound device returned", __func__);
741 return -EINVAL;
742 }
743
Eric Laurent2e140aa2016-06-30 17:14:46 -0700744 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800745 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700746 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700747 audio_extn_sound_trigger_update_device_status(snd_device,
748 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700749 }
vivek mehtab6506412015-08-07 16:55:17 -0700750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800751 return 0;
752}
753
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700754/*
755 legend:
756 uc - existing usecase
757 new_uc - new usecase
758 d1, d11, d2 - SND_DEVICE enums
759 a1, a2 - corresponding ANDROID device enums
760 B, B1, B2 - backend strings
761
762case 1
763 uc->dev d1 (a1) B1
764 new_uc->dev d1 (a1), d2 (a2) B1, B2
765
766 resolution: disable and enable uc->dev on d1
767
768case 2
769 uc->dev d1 (a1) B1
770 new_uc->dev d11 (a1) B1
771
772 resolution: need to switch uc since d1 and d11 are related
773 (e.g. speaker and voice-speaker)
774 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
775
776case 3
777 uc->dev d1 (a1) B1
778 new_uc->dev d2 (a2) B2
779
780 resolution: no need to switch uc
781
782case 4
783 uc->dev d1 (a1) B
784 new_uc->dev d2 (a2) B
785
786 resolution: disable enable uc-dev on d2 since backends match
787 we cannot enable two streams on two different devices if they
788 share the same backend. e.g. if offload is on speaker device using
789 QUAD_MI2S backend and a low-latency stream is started on voice-handset
790 using the same backend, offload must also be switched to voice-handset.
791
792case 5
793 uc->dev d1 (a1) B
794 new_uc->dev d1 (a1), d2 (a2) B
795
796 resolution: disable enable uc-dev on d2 since backends match
797 we cannot enable two streams on two different devices if they
798 share the same backend.
799
800case 6
801 uc->dev d1 a1 B1
802 new_uc->dev d2 a1 B2
803
804 resolution: no need to switch
805
806case 7
807
808 uc->dev d1 (a1), d2 (a2) B1, B2
809 new_uc->dev d1 B1
810
811 resolution: no need to switch
812
813*/
814static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
815 struct audio_usecase *new_uc,
816 snd_device_t new_snd_device)
817{
818 audio_devices_t a1 = uc->stream.out->devices;
819 audio_devices_t a2 = new_uc->stream.out->devices;
820
821 snd_device_t d1 = uc->out_snd_device;
822 snd_device_t d2 = new_snd_device;
823
824 // Treat as a special case when a1 and a2 are not disjoint
825 if ((a1 != a2) && (a1 & a2)) {
826 snd_device_t d3[2];
827 int num_devices = 0;
828 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
829 &num_devices,
830 d3);
831 if (ret < 0) {
832 if (ret != -ENOSYS) {
833 ALOGW("%s failed to split snd_device %d",
834 __func__,
835 popcount(a1) > 1 ? d1 : d2);
836 }
837 goto end;
838 }
839
840 // NB: case 7 is hypothetical and isn't a practical usecase yet.
841 // But if it does happen, we need to give priority to d2 if
842 // the combo devices active on the existing usecase share a backend.
843 // This is because we cannot have a usecase active on a combo device
844 // and a new usecase requests one device in this combo pair.
845 if (platform_check_backends_match(d3[0], d3[1])) {
846 return d2; // case 5
847 } else {
848 return d1; // case 1
849 }
850 } else {
851 if (platform_check_backends_match(d1, d2)) {
852 return d2; // case 2, 4
853 } else {
854 return d1; // case 6, 3
855 }
856 }
857
858end:
859 return d2; // return whatever was calculated before.
860}
861
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700862static void check_and_route_playback_usecases(struct audio_device *adev,
863 struct audio_usecase *uc_info,
864 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865{
866 struct listnode *node;
867 struct audio_usecase *usecase;
868 bool switch_device[AUDIO_USECASE_MAX];
869 int i, num_uc_to_switch = 0;
870
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700871 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
872 uc_info,
873 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700874
Aniket Kumar Lata26483012018-01-31 20:21:42 -0800875 /* For a2dp device reconfigure all active sessions
876 * with new AFE encoder format based on a2dp state
877 */
878 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
879 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
880 audio_extn_a2dp_is_force_device_switch()) {
881 force_routing = true;
882 }
883
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 /*
885 * This function is to make sure that all the usecases that are active on
886 * the hardware codec backend are always routed to any one device that is
887 * handled by the hardware codec.
888 * For example, if low-latency and deep-buffer usecases are currently active
889 * on speaker and out_set_parameters(headset) is received on low-latency
890 * output, then we have to make sure deep-buffer is also switched to headset,
891 * because of the limitation that both the devices cannot be enabled
892 * at the same time as they share the same backend.
893 */
894 /* Disable all the usecases on the shared backend other than the
895 specified usecase */
896 for (i = 0; i < AUDIO_USECASE_MAX; i++)
897 switch_device[i] = false;
898
899 list_for_each(node, &adev->usecase_list) {
900 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700901 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
902 continue;
903
904 if (force_routing ||
905 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700906 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
907 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700908 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
910 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700911 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700912 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700913 switch_device[usecase->id] = true;
914 num_uc_to_switch++;
915 }
916 }
917
918 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919 list_for_each(node, &adev->usecase_list) {
920 usecase = node_to_item(node, struct audio_usecase, list);
921 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700922 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900923 }
924 }
925
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700926 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900927 list_for_each(node, &adev->usecase_list) {
928 usecase = node_to_item(node, struct audio_usecase, list);
929 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700930 d_device = derive_playback_snd_device(usecase, uc_info,
931 snd_device);
932 enable_snd_device(adev, d_device);
933 /* Update the out_snd_device before enabling the audio route */
934 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700935 }
936 }
937
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700938 /* Re-route all the usecases on the shared backend other than the
939 specified usecase to new snd devices */
940 list_for_each(node, &adev->usecase_list) {
941 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700942 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700943 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944 }
945 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700946 }
947}
948
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949static void check_and_route_capture_usecases(struct audio_device *adev,
950 struct audio_usecase *uc_info,
951 snd_device_t snd_device)
952{
953 struct listnode *node;
954 struct audio_usecase *usecase;
955 bool switch_device[AUDIO_USECASE_MAX];
956 int i, num_uc_to_switch = 0;
957
vivek mehta4ed66e62016-04-15 23:33:34 -0700958 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
959
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700960 /*
961 * This function is to make sure that all the active capture usecases
962 * are always routed to the same input sound device.
963 * For example, if audio-record and voice-call usecases are currently
964 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
965 * is received for voice call then we have to make sure that audio-record
966 * usecase is also switched to earpiece i.e. voice-dmic-ef,
967 * because of the limitation that two devices cannot be enabled
968 * at the same time if they share the same backend.
969 */
970 for (i = 0; i < AUDIO_USECASE_MAX; i++)
971 switch_device[i] = false;
972
973 list_for_each(node, &adev->usecase_list) {
974 usecase = node_to_item(node, struct audio_usecase, list);
975 if (usecase->type != PCM_PLAYBACK &&
976 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700977 usecase->in_snd_device != snd_device &&
978 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700979 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
980 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700981 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700982 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700983 switch_device[usecase->id] = true;
984 num_uc_to_switch++;
985 }
986 }
987
988 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700989 list_for_each(node, &adev->usecase_list) {
990 usecase = node_to_item(node, struct audio_usecase, list);
991 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700992 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700993 }
994 }
995
996 list_for_each(node, &adev->usecase_list) {
997 usecase = node_to_item(node, struct audio_usecase, list);
998 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700999 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001000 }
1001 }
1002
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001003 /* Re-route all the usecases on the shared backend other than the
1004 specified usecase to new snd devices */
1005 list_for_each(node, &adev->usecase_list) {
1006 usecase = node_to_item(node, struct audio_usecase, list);
1007 /* Update the in_snd_device only before enabling the audio route */
1008 if (switch_device[usecase->id] ) {
1009 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001010 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001011 }
1012 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001013 }
1014}
1015
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001016/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001017static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001019 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001020 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021
1022 switch (channels) {
1023 /*
1024 * Do not handle stereo output in Multi-channel cases
1025 * Stereo case is handled in normal playback path
1026 */
1027 case 6:
1028 ALOGV("%s: HDMI supports 5.1", __func__);
1029 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1030 break;
1031 case 8:
1032 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
1033 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
1034 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
1035 break;
1036 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001037 ALOGE("HDMI does not support multi channel playback");
1038 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039 break;
1040 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001041 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042}
1043
Andy Hung18859412017-08-09 11:47:21 -07001044static ssize_t read_usb_sup_sample_rates(bool is_playback,
1045 uint32_t *supported_sample_rates,
1046 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001047{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001048 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1049 supported_sample_rates,
1050 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001051#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001052 for (ssize_t i=0; i<count; i++) {
1053 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1054 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001055 }
1056#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001057 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001058}
1059
Haynes Mathew George569b7482017-05-08 14:44:27 -07001060static int read_usb_sup_channel_masks(bool is_playback,
1061 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001062 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001063{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001064 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001065 int channel_count;
1066 uint32_t num_masks = 0;
1067 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1068 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001069 }
Eric Laurent74b55762017-07-09 17:04:53 -07001070 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001071 // start from 2 channels as framework currently doesn't support mono.
1072 // TODO: consider only supporting channel index masks beyond stereo here.
1073 for (channel_count = FCC_2;
1074 channel_count <= channels && num_masks < max_masks;
1075 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001076 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1077 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001078 for (channel_count = FCC_2;
1079 channel_count <= channels && num_masks < max_masks;
1080 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001081 supported_channel_masks[num_masks++] =
1082 audio_channel_mask_for_index_assignment_from_count(channel_count);
1083 }
1084 } else {
1085 // For capture we report all supported channel masks from 1 channel up.
1086 channel_count = MIN_CHANNEL_COUNT;
1087 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1088 // indexed mask
1089 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1090 supported_channel_masks[num_masks++] =
1091 audio_channel_in_mask_from_count(channel_count);
1092 }
1093 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001094#ifdef NDEBUG
1095 for (size_t i = 0; i < num_masks; ++i) {
1096 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1097 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1098 }
1099#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001100 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001101}
1102
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001103static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001104 audio_format_t *supported_formats,
1105 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001106{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001107 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001108 switch (bitwidth) {
1109 case 24:
1110 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001111 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001112 break;
1113 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001114 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001115 break;
1116 case 16:
1117 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001118 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001119 break;
1120 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001121 ALOGV("%s: %s supported format %d", __func__,
1122 is_playback ? "P" : "C", bitwidth);
1123 return 1;
1124}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001125
Haynes Mathew George569b7482017-05-08 14:44:27 -07001126static int read_usb_sup_params_and_compare(bool is_playback,
1127 audio_format_t *format,
1128 audio_format_t *supported_formats,
1129 uint32_t max_formats,
1130 audio_channel_mask_t *mask,
1131 audio_channel_mask_t *supported_channel_masks,
1132 uint32_t max_masks,
1133 uint32_t *rate,
1134 uint32_t *supported_sample_rates,
1135 uint32_t max_rates) {
1136 int ret = 0;
1137 int num_formats;
1138 int num_masks;
1139 int num_rates;
1140 int i;
1141
1142 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1143 max_formats);
1144 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1145 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001146
Haynes Mathew George569b7482017-05-08 14:44:27 -07001147 num_rates = read_usb_sup_sample_rates(is_playback,
1148 supported_sample_rates, max_rates);
1149
1150#define LUT(table, len, what, dflt) \
1151 for (i=0; i<len && (table[i] != what); i++); \
1152 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1153
1154 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1155 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1156 LUT(supported_sample_rates, num_rates, *rate, 0);
1157
1158#undef LUT
1159 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001160}
1161
Andy Hungd9653bd2017-08-01 19:31:39 -07001162static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1163{
1164 // Check if usb is ready.
1165 // The usb device may have been removed quickly after insertion and hence
1166 // no longer available. This will show up as empty channel masks, or rates.
1167
1168 pthread_mutex_lock(&adev->lock);
1169 uint32_t supported_sample_rate;
1170
1171 // we consider usb ready if we can fetch at least one sample rate.
1172 const bool ready = read_usb_sup_sample_rates(
1173 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1174 pthread_mutex_unlock(&adev->lock);
1175 return ready;
1176}
1177
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001178static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1179{
1180 struct audio_usecase *usecase;
1181 struct listnode *node;
1182
1183 list_for_each(node, &adev->usecase_list) {
1184 usecase = node_to_item(node, struct audio_usecase, list);
1185 if (usecase->type == VOICE_CALL) {
1186 ALOGV("%s: usecase id %d", __func__, usecase->id);
1187 return usecase->id;
1188 }
1189 }
1190 return USECASE_INVALID;
1191}
1192
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001193struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1194 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001195{
1196 struct audio_usecase *usecase;
1197 struct listnode *node;
1198
1199 list_for_each(node, &adev->usecase_list) {
1200 usecase = node_to_item(node, struct audio_usecase, list);
1201 if (usecase->id == uc_id)
1202 return usecase;
1203 }
1204 return NULL;
1205}
1206
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001207static bool force_device_switch(struct audio_usecase *usecase)
1208{
1209 if (usecase->stream.out == NULL) {
1210 ALOGE("%s: stream.out is NULL", __func__);
1211 return false;
1212 }
1213
1214 // Force all A2DP output devices to reconfigure for proper AFE encode format
1215 // Also handle a case where in earlier A2DP start failed as A2DP stream was
1216 // in suspended state, hence try to trigger a retry when we again get a routing request.
1217 if ((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1218 audio_extn_a2dp_is_force_device_switch()) {
1219 ALOGD("%s: Force A2DP device switch to update new encoder config", __func__);
1220 return true;
1221 }
1222
1223 return false;
1224}
1225
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001226int select_devices(struct audio_device *adev,
1227 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001229 snd_device_t out_snd_device = SND_DEVICE_NONE;
1230 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001231 struct audio_usecase *usecase = NULL;
1232 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001233 struct audio_usecase *hfp_usecase = NULL;
1234 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001235 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001236 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001237 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1238 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001239
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001240 usecase = get_usecase_from_list(adev, uc_id);
1241 if (usecase == NULL) {
1242 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1243 return -EINVAL;
1244 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001245
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001246 if ((usecase->type == VOICE_CALL) ||
1247 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001248 out_snd_device = platform_get_output_snd_device(adev->platform,
1249 usecase->stream.out->devices);
1250 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001251 usecase->devices = usecase->stream.out->devices;
1252 } else {
1253 /*
1254 * If the voice call is active, use the sound devices of voice call usecase
1255 * so that it would not result any device switch. All the usecases will
1256 * be switched to new device when select_devices() is called for voice call
1257 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001258 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001259 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001260 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001261 vc_usecase = get_usecase_from_list(adev,
1262 get_voice_usecase_id_from_list(adev));
1263 if ((vc_usecase != NULL) &&
1264 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1265 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001266 in_snd_device = vc_usecase->in_snd_device;
1267 out_snd_device = vc_usecase->out_snd_device;
1268 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001269 } else if (audio_extn_hfp_is_active(adev)) {
1270 hfp_ucid = audio_extn_hfp_get_usecase();
1271 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1272 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1273 in_snd_device = hfp_usecase->in_snd_device;
1274 out_snd_device = hfp_usecase->out_snd_device;
1275 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001276 }
1277 if (usecase->type == PCM_PLAYBACK) {
1278 usecase->devices = usecase->stream.out->devices;
1279 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001280 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001281 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001282
Eric Laurentb23d5282013-05-14 15:27:20 -07001283 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001285
1286 if (voip_usecase)
1287 voip_out = voip_usecase->stream.out;
1288
1289 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001290 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001291 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001292 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001293 select_devices(adev, adev->active_input->usecase);
1294 }
1295 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296 } else if (usecase->type == PCM_CAPTURE) {
1297 usecase->devices = usecase->stream.in->device;
1298 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001299 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001300 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001301 if (adev->active_input &&
1302 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1303 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001304
1305 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1306 USECASE_AUDIO_PLAYBACK_VOIP);
1307
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001308 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001309 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1310 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001311 } else if (voip_usecase) {
1312 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001313 } else if (adev->primary_output) {
1314 out_device = adev->primary_output->devices;
1315 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001316 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001317 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001318 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001319 }
1320 }
1321
1322 if (out_snd_device == usecase->out_snd_device &&
1323 in_snd_device == usecase->in_snd_device) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001324 if (!force_device_switch(usecase))
1325 return 0;
1326 }
1327
1328 if (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_is_ready()) {
1329 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
1330 return 0;
1331 }
1332
1333 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP) &&
1334 (!audio_extn_a2dp_is_ready())) {
1335 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
1336 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001337 }
1338
Eric Laurent2bafff12016-03-17 12:17:23 -07001339 if (out_snd_device != SND_DEVICE_NONE &&
1340 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1341 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1342 __func__,
1343 use_case_table[uc_id],
1344 adev->last_logged_snd_device[uc_id][0],
1345 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1346 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1347 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1348 -1,
1349 out_snd_device,
1350 platform_get_snd_device_name(out_snd_device),
1351 platform_get_snd_device_acdb_id(out_snd_device));
1352 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1353 }
1354 if (in_snd_device != SND_DEVICE_NONE &&
1355 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1356 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1357 __func__,
1358 use_case_table[uc_id],
1359 adev->last_logged_snd_device[uc_id][1],
1360 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1361 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1362 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1363 -1,
1364 in_snd_device,
1365 platform_get_snd_device_name(in_snd_device),
1366 platform_get_snd_device_acdb_id(in_snd_device));
1367 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1368 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001370 /*
1371 * Limitation: While in call, to do a device switch we need to disable
1372 * and enable both RX and TX devices though one of them is same as current
1373 * device.
1374 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001375 if ((usecase->type == VOICE_CALL) &&
1376 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1377 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001378 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001379 /* Disable sidetone only if voice call already exists */
1380 if (voice_is_call_state_active(adev))
1381 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001382 }
1383
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001384 /* Disable current sound devices */
1385 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001386 disable_audio_route(adev, usecase);
1387 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388 }
1389
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001390 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001391 disable_audio_route(adev, usecase);
1392 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001393 }
1394
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001395 /* Applicable only on the targets that has external modem.
1396 * New device information should be sent to modem before enabling
1397 * the devices to reduce in-call device switch time.
1398 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001399 if ((usecase->type == VOICE_CALL) &&
1400 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1401 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001402 status = platform_switch_voice_call_enable_device_config(adev->platform,
1403 out_snd_device,
1404 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001405 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001406
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001407 /* Enable new sound devices */
1408 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001409 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001410 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) ||
1411 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001412 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001413 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001414 }
1415
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001416 if (in_snd_device != SND_DEVICE_NONE) {
1417 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001418 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001419 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001420
Eric Laurentb23d5282013-05-14 15:27:20 -07001421 if (usecase->type == VOICE_CALL)
1422 status = platform_switch_voice_call_device_post(adev->platform,
1423 out_snd_device,
1424 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001425
sangwoo170731f2013-06-08 15:36:36 +09001426 usecase->in_snd_device = in_snd_device;
1427 usecase->out_snd_device = out_snd_device;
1428
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001429 audio_extn_tfa_98xx_set_mode();
1430
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001431 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001432
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001433 /* Applicable only on the targets that has external modem.
1434 * Enable device command should be sent to modem only after
1435 * enabling voice call mixer controls
1436 */
vivek mehta765eb642015-08-07 19:46:06 -07001437 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001438 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1439 out_snd_device,
1440 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001441 /* Enable sidetone only if voice call already exists */
1442 if (voice_is_call_state_active(adev))
1443 voice_set_sidetone(adev, out_snd_device, true);
1444 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001445
Eric Laurentf4520b02017-09-20 18:31:58 -07001446 if (usecase == voip_usecase) {
1447 struct stream_out *voip_out = voip_usecase->stream.out;
1448 audio_extn_utils_send_app_type_gain(adev,
1449 voip_out->app_type_cfg.app_type,
1450 &voip_out->app_type_cfg.gain[0]);
1451 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452 return status;
1453}
1454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455static int stop_input_stream(struct stream_in *in)
1456{
1457 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 struct audio_usecase *uc_info;
1459 struct audio_device *adev = in->dev;
1460
Eric Laurent994a6932013-07-17 11:51:42 -07001461 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001463
1464 if (adev->active_input) {
1465 if (adev->active_input->usecase == in->usecase) {
1466 adev->active_input = NULL;
1467 } else {
1468 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1469 __func__,
1470 use_case_table[adev->active_input->usecase],
1471 use_case_table[in->usecase]);
1472 }
1473 }
1474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 uc_info = get_usecase_from_list(adev, in->usecase);
1476 if (uc_info == NULL) {
1477 ALOGE("%s: Could not find the usecase (%d) in the list",
1478 __func__, in->usecase);
1479 return -EINVAL;
1480 }
1481
vivek mehta781065c2017-04-04 12:55:01 -07001482 /* Close in-call recording streams */
1483 voice_check_and_stop_incall_rec_usecase(adev, in);
1484
Eric Laurent150dbfe2013-02-27 14:31:02 -08001485 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001486 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001487
1488 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001489 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001490
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001491 list_remove(&uc_info->list);
1492 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493
Eric Laurent994a6932013-07-17 11:51:42 -07001494 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495 return ret;
1496}
1497
1498int start_input_stream(struct stream_in *in)
1499{
1500 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001501 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502 struct audio_usecase *uc_info;
1503 struct audio_device *adev = in->dev;
1504
Eric Laurent994a6932013-07-17 11:51:42 -07001505 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001506
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001507 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1508 return -EIO;
1509
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001510 if (in->card_status == CARD_STATUS_OFFLINE ||
1511 adev->card_status == CARD_STATUS_OFFLINE) {
1512 ALOGW("in->card_status or adev->card_status offline, try again");
1513 ret = -EAGAIN;
1514 goto error_config;
1515 }
1516
vivek mehta781065c2017-04-04 12:55:01 -07001517 /* Check if source matches incall recording usecase criteria */
1518 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1519 if (ret)
1520 goto error_config;
1521 else
1522 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1523
Eric Laurentb23d5282013-05-14 15:27:20 -07001524 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 if (in->pcm_device_id < 0) {
1526 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1527 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001528 ret = -EINVAL;
1529 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001531
1532 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1534 uc_info->id = in->usecase;
1535 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001536 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001537 uc_info->devices = in->device;
1538 uc_info->in_snd_device = SND_DEVICE_NONE;
1539 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001541 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001542
Wei Wangf4837d52017-11-21 14:51:20 -08001543 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001544 audio_extn_perf_lock_acquire();
1545
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001546 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547
Eric Laurent0e46adf2016-12-16 12:49:24 -08001548 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001549 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001550 ALOGE("%s: pcm stream not ready", __func__);
1551 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001552 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001553 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001554 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001555 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1556 goto error_open;
1557 }
1558 } else {
1559 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1560 unsigned int pcm_open_retry_count = 0;
1561
1562 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1563 flags |= PCM_MMAP | PCM_NOIRQ;
1564 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1565 } else if (in->realtime) {
1566 flags |= PCM_MMAP | PCM_NOIRQ;
1567 }
1568
1569 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1570 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1571
1572 while (1) {
1573 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1574 flags, &in->config);
1575 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1576 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1577 if (in->pcm != NULL) {
1578 pcm_close(in->pcm);
1579 in->pcm = NULL;
1580 }
1581 if (pcm_open_retry_count-- == 0) {
1582 ret = -EIO;
1583 goto error_open;
1584 }
1585 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1586 continue;
1587 }
1588 break;
1589 }
1590
1591 ALOGV("%s: pcm_prepare", __func__);
1592 ret = pcm_prepare(in->pcm);
1593 if (ret < 0) {
1594 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001595 pcm_close(in->pcm);
1596 in->pcm = NULL;
1597 goto error_open;
1598 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001599 if (in->realtime) {
1600 ret = pcm_start(in->pcm);
1601 if (ret < 0) {
1602 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1603 pcm_close(in->pcm);
1604 in->pcm = NULL;
1605 goto error_open;
1606 }
1607 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001608 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001609 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001610 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001611 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001612 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001613
Eric Laurent0e46adf2016-12-16 12:49:24 -08001614 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001615
1616error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001617 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001618 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001619 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001620
1621error_config:
1622 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001623 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001624 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625}
1626
Eric Laurenta1478072015-09-21 17:21:52 -07001627void lock_input_stream(struct stream_in *in)
1628{
1629 pthread_mutex_lock(&in->pre_lock);
1630 pthread_mutex_lock(&in->lock);
1631 pthread_mutex_unlock(&in->pre_lock);
1632}
1633
1634void lock_output_stream(struct stream_out *out)
1635{
1636 pthread_mutex_lock(&out->pre_lock);
1637 pthread_mutex_lock(&out->lock);
1638 pthread_mutex_unlock(&out->pre_lock);
1639}
1640
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001641/* must be called with out->lock locked */
1642static int send_offload_cmd_l(struct stream_out* out, int command)
1643{
1644 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1645
1646 ALOGVV("%s %d", __func__, command);
1647
1648 cmd->cmd = command;
1649 list_add_tail(&out->offload_cmd_list, &cmd->node);
1650 pthread_cond_signal(&out->offload_cond);
1651 return 0;
1652}
1653
1654/* must be called iwth out->lock locked */
1655static void stop_compressed_output_l(struct stream_out *out)
1656{
1657 out->offload_state = OFFLOAD_STATE_IDLE;
1658 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001659 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001660 if (out->compr != NULL) {
1661 compress_stop(out->compr);
1662 while (out->offload_thread_blocked) {
1663 pthread_cond_wait(&out->cond, &out->lock);
1664 }
1665 }
1666}
1667
1668static void *offload_thread_loop(void *context)
1669{
1670 struct stream_out *out = (struct stream_out *) context;
1671 struct listnode *item;
1672
1673 out->offload_state = OFFLOAD_STATE_IDLE;
1674 out->playback_started = 0;
1675
1676 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1677 set_sched_policy(0, SP_FOREGROUND);
1678 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1679
1680 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001681 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001682 for (;;) {
1683 struct offload_cmd *cmd = NULL;
1684 stream_callback_event_t event;
1685 bool send_callback = false;
1686
1687 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1688 __func__, list_empty(&out->offload_cmd_list),
1689 out->offload_state);
1690 if (list_empty(&out->offload_cmd_list)) {
1691 ALOGV("%s SLEEPING", __func__);
1692 pthread_cond_wait(&out->offload_cond, &out->lock);
1693 ALOGV("%s RUNNING", __func__);
1694 continue;
1695 }
1696
1697 item = list_head(&out->offload_cmd_list);
1698 cmd = node_to_item(item, struct offload_cmd, node);
1699 list_remove(item);
1700
1701 ALOGVV("%s STATE %d CMD %d out->compr %p",
1702 __func__, out->offload_state, cmd->cmd, out->compr);
1703
1704 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1705 free(cmd);
1706 break;
1707 }
1708
1709 if (out->compr == NULL) {
1710 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001711 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001712 pthread_cond_signal(&out->cond);
1713 continue;
1714 }
1715 out->offload_thread_blocked = true;
1716 pthread_mutex_unlock(&out->lock);
1717 send_callback = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001718 switch (cmd->cmd) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001719 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1720 compress_wait(out->compr, -1);
1721 send_callback = true;
1722 event = STREAM_CBK_EVENT_WRITE_READY;
1723 break;
1724 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001725 compress_next_track(out->compr);
1726 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001727 send_callback = true;
1728 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001729 /* Resend the metadata for next iteration */
1730 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 break;
1732 case OFFLOAD_CMD_DRAIN:
1733 compress_drain(out->compr);
1734 send_callback = true;
1735 event = STREAM_CBK_EVENT_DRAIN_READY;
1736 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001737 case OFFLOAD_CMD_ERROR:
1738 send_callback = true;
1739 event = STREAM_CBK_EVENT_ERROR;
1740 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001741 default:
1742 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1743 break;
1744 }
Eric Laurenta1478072015-09-21 17:21:52 -07001745 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746 out->offload_thread_blocked = false;
1747 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001748 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001749 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001750 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001751 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001752 free(cmd);
1753 }
1754
1755 pthread_cond_signal(&out->cond);
1756 while (!list_empty(&out->offload_cmd_list)) {
1757 item = list_head(&out->offload_cmd_list);
1758 list_remove(item);
1759 free(node_to_item(item, struct offload_cmd, node));
1760 }
1761 pthread_mutex_unlock(&out->lock);
1762
1763 return NULL;
1764}
1765
1766static int create_offload_callback_thread(struct stream_out *out)
1767{
1768 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1769 list_init(&out->offload_cmd_list);
1770 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1771 offload_thread_loop, out);
1772 return 0;
1773}
1774
1775static int destroy_offload_callback_thread(struct stream_out *out)
1776{
Eric Laurenta1478072015-09-21 17:21:52 -07001777 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001778 stop_compressed_output_l(out);
1779 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1780
1781 pthread_mutex_unlock(&out->lock);
1782 pthread_join(out->offload_thread, (void **) NULL);
1783 pthread_cond_destroy(&out->offload_cond);
1784
1785 return 0;
1786}
1787
Eric Laurent07eeafd2013-10-06 12:52:49 -07001788static bool allow_hdmi_channel_config(struct audio_device *adev)
1789{
1790 struct listnode *node;
1791 struct audio_usecase *usecase;
1792 bool ret = true;
1793
1794 list_for_each(node, &adev->usecase_list) {
1795 usecase = node_to_item(node, struct audio_usecase, list);
1796 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1797 /*
1798 * If voice call is already existing, do not proceed further to avoid
1799 * disabling/enabling both RX and TX devices, CSD calls, etc.
1800 * Once the voice call done, the HDMI channels can be configured to
1801 * max channels of remaining use cases.
1802 */
1803 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001804 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001805 __func__);
1806 ret = false;
1807 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001808 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1809 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001810 "no change in HDMI channels", __func__);
1811 ret = false;
1812 break;
1813 }
1814 }
1815 }
1816 return ret;
1817}
1818
1819static int check_and_set_hdmi_channels(struct audio_device *adev,
1820 unsigned int channels)
1821{
1822 struct listnode *node;
1823 struct audio_usecase *usecase;
1824
1825 /* Check if change in HDMI channel config is allowed */
1826 if (!allow_hdmi_channel_config(adev))
1827 return 0;
1828
1829 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001830 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001831 return 0;
1832 }
1833
1834 platform_set_hdmi_channels(adev->platform, channels);
1835 adev->cur_hdmi_channels = channels;
1836
1837 /*
1838 * Deroute all the playback streams routed to HDMI so that
1839 * the back end is deactivated. Note that backend will not
1840 * be deactivated if any one stream is connected to it.
1841 */
1842 list_for_each(node, &adev->usecase_list) {
1843 usecase = node_to_item(node, struct audio_usecase, list);
1844 if (usecase->type == PCM_PLAYBACK &&
1845 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001846 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001847 }
1848 }
1849
1850 /*
1851 * Enable all the streams disabled above. Now the HDMI backend
1852 * will be activated with new channel configuration
1853 */
1854 list_for_each(node, &adev->usecase_list) {
1855 usecase = node_to_item(node, struct audio_usecase, list);
1856 if (usecase->type == PCM_PLAYBACK &&
1857 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001858 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001859 }
1860 }
1861
1862 return 0;
1863}
1864
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865static int stop_output_stream(struct stream_out *out)
1866{
1867 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868 struct audio_usecase *uc_info;
1869 struct audio_device *adev = out->dev;
1870
Eric Laurent994a6932013-07-17 11:51:42 -07001871 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001872 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873 uc_info = get_usecase_from_list(adev, out->usecase);
1874 if (uc_info == NULL) {
1875 ALOGE("%s: Could not find the usecase (%d) in the list",
1876 __func__, out->usecase);
1877 return -EINVAL;
1878 }
1879
Haynes Mathew George41f86652014-06-17 14:22:15 -07001880 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1881 if (adev->visualizer_stop_output != NULL)
1882 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1883 if (adev->offload_effects_stop_output != NULL)
1884 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001885 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1886 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1887 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001888 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001889
Eric Laurent150dbfe2013-02-27 14:31:02 -08001890 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001891 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001892
1893 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001894 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001896 list_remove(&uc_info->list);
1897 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001898
Eric Laurent0499d4f2014-08-25 22:39:29 -05001899 audio_extn_extspk_update(adev->extspk);
1900
Eric Laurent07eeafd2013-10-06 12:52:49 -07001901 /* Must be called after removing the usecase from list */
1902 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1903 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001904 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1905 struct listnode *node;
1906 struct audio_usecase *usecase;
1907 list_for_each(node, &adev->usecase_list) {
1908 usecase = node_to_item(node, struct audio_usecase, list);
1909 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1910 select_devices(adev, usecase->id);
1911 }
1912 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001913
Eric Laurent994a6932013-07-17 11:51:42 -07001914 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001915 return ret;
1916}
1917
1918int start_output_stream(struct stream_out *out)
1919{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921 struct audio_usecase *uc_info;
1922 struct audio_device *adev = out->dev;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001923 bool a2dp_combo = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924
Eric Laurent994a6932013-07-17 11:51:42 -07001925 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001926 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001927
1928 if (out->card_status == CARD_STATUS_OFFLINE ||
1929 adev->card_status == CARD_STATUS_OFFLINE) {
1930 ALOGW("out->card_status or adev->card_status offline, try again");
1931 ret = -EAGAIN;
1932 goto error_config;
1933 }
1934
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001935 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
1936 if (!audio_extn_a2dp_is_ready()) {
1937 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
1938 a2dp_combo = true;
1939 } else {
1940 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
1941 ALOGE("%s: A2DP profile is not ready, return error", __func__);
1942 ret = -EAGAIN;
1943 goto error_config;
1944 }
1945 }
1946 }
1947 }
Eric Laurentb23d5282013-05-14 15:27:20 -07001948 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 if (out->pcm_device_id < 0) {
1950 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1951 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001952 ret = -EINVAL;
1953 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954 }
1955
1956 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1957 uc_info->id = out->usecase;
1958 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001959 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001960 uc_info->devices = out->devices;
1961 uc_info->in_snd_device = SND_DEVICE_NONE;
1962 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001963
Eric Laurent07eeafd2013-10-06 12:52:49 -07001964 /* This must be called before adding this usecase to the list */
1965 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1966 check_and_set_hdmi_channels(adev, out->config.channels);
1967
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001968 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969
Wei Wangf4837d52017-11-21 14:51:20 -08001970 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001971 audio_extn_perf_lock_acquire();
1972
Aniket Kumar Lata26483012018-01-31 20:21:42 -08001973 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
1974 (!audio_extn_a2dp_is_ready())) {
1975 if (!a2dp_combo) {
1976 check_a2dp_restore_l(adev, out, false);
1977 } else {
1978 audio_devices_t dev = out->devices;
1979 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
1980 select_devices(adev, out->usecase);
1981 out->devices = dev;
1982 }
1983 } else {
1984 select_devices(adev, out->usecase);
1985 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001986
Eric Laurent0499d4f2014-08-25 22:39:29 -05001987 audio_extn_extspk_update(adev->extspk);
1988
Andy Hung31aca912014-03-20 17:14:59 -07001989 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001990 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001991 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1992 out->pcm = NULL;
1993 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1994 COMPRESS_IN, &out->compr_config);
1995 if (out->compr && !is_compress_ready(out->compr)) {
1996 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1997 compress_close(out->compr);
1998 out->compr = NULL;
1999 ret = -EIO;
2000 goto error_open;
2001 }
2002 if (out->offload_callback)
2003 compress_nonblock(out->compr, out->non_blocking);
2004
2005 if (adev->visualizer_start_output != NULL)
2006 adev->visualizer_start_output(out->handle, out->pcm_device_id);
2007 if (adev->offload_effects_start_output != NULL)
2008 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
2009 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002010 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002011 ALOGE("%s: pcm stream not ready", __func__);
2012 goto error_open;
2013 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002014 ret = pcm_start(out->pcm);
2015 if (ret < 0) {
2016 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2017 goto error_open;
2018 }
2019 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07002020 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002021 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002022
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002023 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
2024 flags |= PCM_MMAP | PCM_NOIRQ;
2025 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002026 } else if (out->realtime) {
2027 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07002028 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002029
2030 while (1) {
2031 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2032 flags, &out->config);
2033 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2034 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2035 if (out->pcm != NULL) {
2036 pcm_close(out->pcm);
2037 out->pcm = NULL;
2038 }
2039 if (pcm_open_retry_count-- == 0) {
2040 ret = -EIO;
2041 goto error_open;
2042 }
2043 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2044 continue;
2045 }
2046 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002047 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07002048 ALOGV("%s: pcm_prepare", __func__);
2049 if (pcm_is_ready(out->pcm)) {
2050 ret = pcm_prepare(out->pcm);
2051 if (ret < 0) {
2052 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2053 pcm_close(out->pcm);
2054 out->pcm = NULL;
2055 goto error_open;
2056 }
2057 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002058 if (out->realtime) {
2059 ret = pcm_start(out->pcm);
2060 if (ret < 0) {
2061 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
2062 pcm_close(out->pcm);
2063 out->pcm = NULL;
2064 goto error_open;
2065 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002066 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002067 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07002068 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08002069 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002070 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002071 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07002072
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08002073 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
2074 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2075 audio_low_latency_hint_start();
2076 }
2077
vivek mehtae59cfb22017-06-16 15:57:11 -07002078 // consider a scenario where on pause lower layers are tear down.
2079 // so on resume, swap mixer control need to be sent only when
2080 // backend is active, hence rather than sending from enable device
2081 // sending it from start of streamtream
2082
2083 platform_set_swap_channels(adev, true);
2084
Eric Laurent994a6932013-07-17 11:51:42 -07002085 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002086 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002087error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08002088 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07002089 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002091error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002092 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002093}
2094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002095static int check_input_parameters(uint32_t sample_rate,
2096 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002097 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002099 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2100 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002101 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2102 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002103 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2104 return -EINVAL;
2105 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106
Eric Laurent74b55762017-07-09 17:04:53 -07002107 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2108 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002109 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002110 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002111 return -EINVAL;
2112 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113
2114 switch (sample_rate) {
2115 case 8000:
2116 case 11025:
2117 case 12000:
2118 case 16000:
2119 case 22050:
2120 case 24000:
2121 case 32000:
2122 case 44100:
2123 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002124 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 break;
2126 default:
vivek mehtadae44712015-07-27 14:13:18 -07002127 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128 return -EINVAL;
2129 }
2130
2131 return 0;
2132}
2133
vivek mehtaa68fea62017-06-08 19:04:02 -07002134static size_t get_stream_buffer_size(size_t duration_ms,
2135 uint32_t sample_rate,
2136 audio_format_t format,
2137 int channel_count,
2138 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139{
2140 size_t size = 0;
2141
vivek mehtaa68fea62017-06-08 19:04:02 -07002142 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002143 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002144 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002145
2146 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147
Glenn Kasten4f993392014-05-14 07:30:48 -07002148 /* make sure the size is multiple of 32 bytes
2149 * At 48 kHz mono 16-bit PCM:
2150 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2151 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2152 */
2153 size += 0x1f;
2154 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002155
2156 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157}
2158
2159static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2160{
2161 struct stream_out *out = (struct stream_out *)stream;
2162
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002163 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164}
2165
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002166static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167{
2168 return -ENOSYS;
2169}
2170
2171static size_t out_get_buffer_size(const struct audio_stream *stream)
2172{
2173 struct stream_out *out = (struct stream_out *)stream;
2174
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002175 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2176 return out->compr_config.fragment_size;
2177 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002178 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002179 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180}
2181
2182static uint32_t out_get_channels(const struct audio_stream *stream)
2183{
2184 struct stream_out *out = (struct stream_out *)stream;
2185
2186 return out->channel_mask;
2187}
2188
2189static audio_format_t out_get_format(const struct audio_stream *stream)
2190{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002191 struct stream_out *out = (struct stream_out *)stream;
2192
2193 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194}
2195
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002196static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197{
2198 return -ENOSYS;
2199}
2200
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002201/* must be called with out->lock locked */
2202static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203{
2204 struct stream_out *out = (struct stream_out *)stream;
2205 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002206 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002209 if (adev->adm_deregister_stream)
2210 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002211 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2214 if (out->pcm) {
2215 pcm_close(out->pcm);
2216 out->pcm = NULL;
2217 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002218 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002219 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002220 out->playback_started = false;
2221 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002222 } else {
2223 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002224 out->gapless_mdata.encoder_delay = 0;
2225 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002226 if (out->compr != NULL) {
2227 compress_close(out->compr);
2228 out->compr = NULL;
2229 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002230 }
Phil Burkbc991042017-02-24 08:06:44 -08002231 if (do_stop) {
2232 stop_output_stream(out);
2233 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002234 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002236 return 0;
2237}
2238
2239static int out_standby(struct audio_stream *stream)
2240{
2241 struct stream_out *out = (struct stream_out *)stream;
2242
2243 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2244 out->usecase, use_case_table[out->usecase]);
2245
2246 lock_output_stream(out);
2247 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002248 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002249 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 return 0;
2251}
2252
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002253static int out_on_error(struct audio_stream *stream)
2254{
2255 struct stream_out *out = (struct stream_out *)stream;
2256 struct audio_device *adev = out->dev;
2257 bool do_standby = false;
2258
2259 lock_output_stream(out);
2260 if (!out->standby) {
2261 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2262 stop_compressed_output_l(out);
2263 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2264 } else
2265 do_standby = true;
2266 }
2267 pthread_mutex_unlock(&out->lock);
2268
2269 if (do_standby)
2270 return out_standby(&out->stream.common);
2271
2272 return 0;
2273}
2274
Andy Hung7401c7c2016-09-21 12:41:21 -07002275static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002276{
Andy Hung7401c7c2016-09-21 12:41:21 -07002277 struct stream_out *out = (struct stream_out *)stream;
2278
2279 // We try to get the lock for consistency,
2280 // but it isn't necessary for these variables.
2281 // If we're not in standby, we may be blocked on a write.
2282 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2283 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2284 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2285
2286 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002287 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002288 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002289
2290 // dump error info
2291 (void)error_log_dump(
2292 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002293
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294 return 0;
2295}
2296
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002297static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2298{
2299 int ret = 0;
2300 char value[32];
2301 struct compr_gapless_mdata tmp_mdata;
2302
2303 if (!out || !parms) {
2304 return -EINVAL;
2305 }
2306
2307 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2308 if (ret >= 0) {
2309 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2310 } else {
2311 return -EINVAL;
2312 }
2313
2314 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2315 if (ret >= 0) {
2316 tmp_mdata.encoder_padding = atoi(value);
2317 } else {
2318 return -EINVAL;
2319 }
2320
2321 out->gapless_mdata = tmp_mdata;
2322 out->send_new_metadata = 1;
2323 ALOGV("%s new encoder delay %u and padding %u", __func__,
2324 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2325
2326 return 0;
2327}
2328
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002329static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2330{
2331 return out == adev->primary_output || out == adev->voice_tx_output;
2332}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002333
Kevin Rocard1e02c882017-08-09 15:26:07 -07002334static int get_alive_usb_card(struct str_parms* parms) {
2335 int card;
2336 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2337 !audio_extn_usb_alive(card)) {
2338 return card;
2339 }
2340 return -ENODEV;
2341}
2342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002343static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2344{
2345 struct stream_out *out = (struct stream_out *)stream;
2346 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002347 struct audio_usecase *usecase;
2348 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002349 struct str_parms *parms;
2350 char value[32];
2351 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002352 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002353 int status = 0;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002354 bool bypass_a2dp = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355
Eric Laurent2e140aa2016-06-30 17:14:46 -07002356 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002357 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002358 parms = str_parms_create_str(kvpairs);
2359 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2360 if (ret >= 0) {
2361 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002362
Eric Laurenta1478072015-09-21 17:21:52 -07002363 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002364
2365 // The usb driver needs to be closed after usb device disconnection
2366 // otherwise audio is no longer played on the new usb devices.
2367 // By forcing the stream in standby, the usb stack refcount drops to 0
2368 // and the driver is closed.
2369 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2370 audio_is_usb_out_device(out->devices)) {
2371 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2372 out_standby_l(&out->stream.common);
2373 }
2374
Eric Laurent150dbfe2013-02-27 14:31:02 -08002375 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002377 /*
2378 * When HDMI cable is unplugged the music playback is paused and
2379 * the policy manager sends routing=0. But the audioflinger
2380 * continues to write data until standby time (3sec).
2381 * As the HDMI core is turned off, the write gets blocked.
2382 * Avoid this by routing audio to speaker until standby.
2383 */
2384 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2385 val == AUDIO_DEVICE_NONE) {
2386 val = AUDIO_DEVICE_OUT_SPEAKER;
2387 }
2388
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002389 /*
2390 * When A2DP is disconnected the
2391 * music playback is paused and the policy manager sends routing=0
2392 * But the audioflingercontinues to write data until standby time
2393 * (3sec). As BT is turned off, the write gets blocked.
2394 * Avoid this by routing audio to speaker until standby.
2395 */
2396 if ((out->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) &&
2397 (val == AUDIO_DEVICE_NONE) &&
2398 !audio_extn_a2dp_is_ready()) {
2399 val = AUDIO_DEVICE_OUT_SPEAKER;
2400 }
2401
2402 /* To avoid a2dp to sco overlapping / BT device improper state
2403 * check with BT lib about a2dp streaming support before routing
2404 */
2405 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
2406 if (!audio_extn_a2dp_is_ready()) {
2407 if (val & AUDIO_DEVICE_OUT_SPEAKER) {
2408 //combo usecase just by pass a2dp
2409 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
2410 bypass_a2dp = true;
2411 } else {
2412 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
2413 /* update device to a2dp and don't route as BT returned error
2414 * However it is still possible a2dp routing called because
2415 * of current active device disconnection (like wired headset)
2416 */
2417 out->devices = val;
2418 pthread_mutex_unlock(&out->lock);
2419 pthread_mutex_unlock(&adev->lock);
2420 status = -ENOSYS;
2421 goto routing_fail;
2422 }
2423 }
2424 }
2425
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002426 audio_devices_t new_dev = val;
2427
2428 // Workaround: If routing to an non existing usb device, fail gracefully
2429 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002430 int card;
2431 if (audio_is_usb_out_device(new_dev) &&
2432 (card = get_alive_usb_card(parms)) >= 0) {
2433
2434 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002435 pthread_mutex_unlock(&adev->lock);
2436 pthread_mutex_unlock(&out->lock);
2437 status = -ENOSYS;
2438 goto routing_fail;
2439 }
2440
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002441 /*
2442 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002443 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002444 * the select_devices(). But how do we undo this?
2445 *
2446 * For example, music playback is active on headset (deep-buffer usecase)
2447 * and if we go to ringtones and select a ringtone, low-latency usecase
2448 * will be started on headset+speaker. As we can't enable headset+speaker
2449 * and headset devices at the same time, select_devices() switches the music
2450 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2451 * So when the ringtone playback is completed, how do we undo the same?
2452 *
2453 * We are relying on the out_set_parameters() call on deep-buffer output,
2454 * once the ringtone playback is ended.
2455 * NOTE: We should not check if the current devices are same as new devices.
2456 * Because select_devices() must be called to switch back the music
2457 * playback to headset.
2458 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002459 if (new_dev != AUDIO_DEVICE_NONE) {
2460 bool same_dev = out->devices == new_dev;
2461 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002462
Eric Laurenta7657192014-10-09 21:09:33 -07002463 if (output_drives_call(adev, out)) {
2464 if (!voice_is_in_call(adev)) {
2465 if (adev->mode == AUDIO_MODE_IN_CALL) {
2466 adev->current_call_output = out;
2467 ret = voice_start_call(adev);
2468 }
2469 } else {
2470 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002471 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002472 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002473 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002474
2475 if (!out->standby) {
2476 if (!same_dev) {
2477 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002478 // inform adm before actual routing to prevent glitches.
2479 if (adev->adm_on_routing_change) {
2480 adev->adm_on_routing_change(adev->adm_data,
2481 out->handle);
2482 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002483 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002484 if (!bypass_a2dp) {
2485 select_devices(adev, out->usecase);
2486 } else {
2487 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
2488 select_devices(adev, out->usecase);
2489 out->devices = new_dev;
2490 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002491 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002492
2493 // on device switch force swap, lower functions will make sure
2494 // to check if swap is allowed or not.
2495
2496 if (!same_dev)
2497 platform_set_swap_channels(adev, true);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002498
2499 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2500 out->a2dp_compress_mute &&
2501 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_is_ready())) {
2502 pthread_mutex_lock(&out->compr_mute_lock);
2503 out->a2dp_compress_mute = false;
2504 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
2505 pthread_mutex_unlock(&out->compr_mute_lock);
2506 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002507 }
2508
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002509 }
2510
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002512 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002513
2514 /*handles device and call state changes*/
2515 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002517 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002518
2519 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2520 parse_compress_metadata(out, parms);
2521 }
2522
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002524 ALOGV("%s: exit: code(%d)", __func__, status);
2525 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526}
2527
Haynes Mathew George569b7482017-05-08 14:44:27 -07002528static bool stream_get_parameter_channels(struct str_parms *query,
2529 struct str_parms *reply,
2530 audio_channel_mask_t *supported_channel_masks) {
2531 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002534 size_t i, j;
2535
2536 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2537 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 value[0] = '\0';
2539 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002540 while (supported_channel_masks[i] != 0) {
2541 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2542 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 if (!first) {
2544 strcat(value, "|");
2545 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002546 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 first = false;
2548 break;
2549 }
2550 }
2551 i++;
2552 }
2553 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002554 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002555 return ret >= 0;
2556}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002557
Haynes Mathew George569b7482017-05-08 14:44:27 -07002558static bool stream_get_parameter_formats(struct str_parms *query,
2559 struct str_parms *reply,
2560 audio_format_t *supported_formats) {
2561 int ret = -1;
2562 char value[256];
2563 int i;
2564
2565 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2566 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002567 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002568 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002569 case AUDIO_FORMAT_PCM_16_BIT:
2570 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2571 break;
2572 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2573 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2574 break;
2575 case AUDIO_FORMAT_PCM_32_BIT:
2576 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2577 break;
2578 default:
2579 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002580 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002581 break;
2582 }
2583 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002584 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002585 return ret >= 0;
2586}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002587
Haynes Mathew George569b7482017-05-08 14:44:27 -07002588static bool stream_get_parameter_rates(struct str_parms *query,
2589 struct str_parms *reply,
2590 uint32_t *supported_sample_rates) {
2591
2592 int i;
2593 char value[256];
2594 int ret = -1;
2595 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2596 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002597 value[0] = '\0';
2598 i=0;
2599 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002600 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002601 int avail = sizeof(value) - cursor;
2602 ret = snprintf(value + cursor, avail, "%s%d",
2603 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002604 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002605 if (ret < 0 || ret >= avail) {
2606 // if cursor is at the last element of the array
2607 // overwrite with \0 is duplicate work as
2608 // snprintf already put a \0 in place.
2609 // else
2610 // we had space to write the '|' at value[cursor]
2611 // (which will be overwritten) or no space to fill
2612 // the first element (=> cursor == 0)
2613 value[cursor] = '\0';
2614 break;
2615 }
2616 cursor += ret;
2617 ++i;
2618 }
2619 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2620 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002621 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002622 return ret >= 0;
2623}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002624
Haynes Mathew George569b7482017-05-08 14:44:27 -07002625static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2626{
2627 struct stream_out *out = (struct stream_out *)stream;
2628 struct str_parms *query = str_parms_create_str(keys);
2629 char *str;
2630 struct str_parms *reply = str_parms_create();
2631 bool replied = false;
2632 ALOGV("%s: enter: keys - %s", __func__, keys);
2633
2634 replied |= stream_get_parameter_channels(query, reply,
2635 &out->supported_channel_masks[0]);
2636 replied |= stream_get_parameter_formats(query, reply,
2637 &out->supported_formats[0]);
2638 replied |= stream_get_parameter_rates(query, reply,
2639 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002640 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 str = str_parms_to_str(reply);
2642 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002643 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 }
2645 str_parms_destroy(query);
2646 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002647 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 return str;
2649}
2650
2651static uint32_t out_get_latency(const struct audio_stream_out *stream)
2652{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002653 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002655 uint32_t latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002657 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2658 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002659 else if ((out->realtime) ||
2660 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002661 // since the buffer won't be filled up faster than realtime,
2662 // return a smaller number
2663 period_ms = (out->af_period_multiplier * out->config.period_size *
2664 1000) / (out->config.rate);
2665 hw_delay = platform_render_latency(out->usecase)/1000;
2666 return period_ms + hw_delay;
2667 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002668
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002669 latency = (out->config.period_count * out->config.period_size * 1000) /
2670 (out->config.rate);
2671
2672 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
2673 latency += audio_extn_a2dp_get_encoder_latency();
2674
2675 return latency;
2676}
2677
2678static int set_compr_volume(struct audio_stream_out *stream, float left,
2679 float right)
2680{
2681 struct stream_out *out = (struct stream_out *)stream;
2682 int volume[2];
2683 char mixer_ctl_name[128];
2684 struct audio_device *adev = out->dev;
2685 struct mixer_ctl *ctl;
2686 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2687 PCM_PLAYBACK);
2688
2689 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2690 "Compress Playback %d Volume", pcm_device_id);
2691 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2692 if (!ctl) {
2693 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2694 __func__, mixer_ctl_name);
2695 return -EINVAL;
2696 }
2697 ALOGV("%s: ctl for mixer cmd - %s, left %f, right %f",
2698 __func__, mixer_ctl_name, left, right);
2699 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2700 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2701 mixer_ctl_set_array(ctl, volume, sizeof(volume) / sizeof(volume[0]));
2702
2703 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704}
2705
2706static int out_set_volume(struct audio_stream_out *stream, float left,
2707 float right)
2708{
Eric Laurenta9024de2013-04-04 09:19:12 -07002709 struct stream_out *out = (struct stream_out *)stream;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002710 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002711
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002712 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002713 /* only take left channel into account: the API is for stereo anyway */
2714 out->muted = (left == 0.0f);
2715 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002716 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002717 pthread_mutex_lock(&out->compr_mute_lock);
2718 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
2719 if (!out->a2dp_compress_mute)
2720 ret = set_compr_volume(stream, left, right);
2721 out->volume_l = left;
2722 out->volume_r = right;
2723 pthread_mutex_unlock(&out->compr_mute_lock);
2724 return ret;
vivek mehtaa68fea62017-06-08 19:04:02 -07002725 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002726 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2727 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2728 if (!out->standby) {
2729 // if in standby, cached volume will be sent after stream is opened
2730 audio_extn_utils_send_app_type_gain(out->dev,
2731 out->app_type_cfg.app_type,
2732 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002733 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002734 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002735 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 return -ENOSYS;
2738}
2739
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002740// note: this call is safe only if the stream_cb is
2741// removed first in close_output_stream (as is done now).
2742static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2743{
2744 if (!stream || !parms)
2745 return;
2746
2747 struct stream_out *out = (struct stream_out *)stream;
2748 struct audio_device *adev = out->dev;
2749
2750 card_status_t status;
2751 int card;
2752 if (parse_snd_card_status(parms, &card, &status) < 0)
2753 return;
2754
2755 pthread_mutex_lock(&adev->lock);
2756 bool valid_cb = (card == adev->snd_card);
2757 pthread_mutex_unlock(&adev->lock);
2758
2759 if (!valid_cb)
2760 return;
2761
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002762 lock_output_stream(out);
2763 if (out->card_status != status)
2764 out->card_status = status;
2765 pthread_mutex_unlock(&out->lock);
2766
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002767 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2768 use_case_table[out->usecase],
2769 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2770
2771 if (status == CARD_STATUS_OFFLINE)
2772 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002773
2774 return;
2775}
2776
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002777#ifdef NO_AUDIO_OUT
2778static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002779 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002780{
2781 struct stream_out *out = (struct stream_out *)stream;
2782
2783 /* No Output device supported other than BT for playback.
2784 * Sleep for the amount of buffer duration
2785 */
Eric Laurenta1478072015-09-21 17:21:52 -07002786 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002787 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2788 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002789 out_get_sample_rate(&out->stream.common));
2790 pthread_mutex_unlock(&out->lock);
2791 return bytes;
2792}
2793#endif
2794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2796 size_t bytes)
2797{
2798 struct stream_out *out = (struct stream_out *)stream;
2799 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002800 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002801 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802
Eric Laurenta1478072015-09-21 17:21:52 -07002803 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002804 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002805 const size_t frame_size = audio_stream_out_frame_size(stream);
2806 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002807
Eric Laurent0e46adf2016-12-16 12:49:24 -08002808 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2809 error_code = ERROR_CODE_WRITE;
2810 goto exit;
2811 }
Aniket Kumar Lata26483012018-01-31 20:21:42 -08002812
2813 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
2814 (audio_extn_a2dp_is_suspended())) {
2815 if (!(out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2816 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
2817 ret = -EIO;
2818 goto exit;
2819 }
2820 }
2821 }
2822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002824 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002825 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002827
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002828 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002830 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002831 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 goto exit;
2833 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002834
vivek mehta40125092017-08-21 18:48:51 -07002835 // after standby always force set last known cal step
2836 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2837 ALOGD("%s: retry previous failed cal level set", __func__);
2838 send_gain_dep_calibration_l();
2839 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002842 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002843 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002844 if (out->send_new_metadata) {
2845 ALOGVV("send new gapless metadata");
2846 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2847 out->send_new_metadata = 0;
2848 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002849 unsigned int avail;
2850 struct timespec tstamp;
2851 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2852 /* Do not limit write size if the available frames count is unknown */
2853 if (ret != 0) {
2854 avail = bytes;
2855 }
2856 if (avail == 0) {
2857 ret = 0;
2858 } else {
2859 if (avail > bytes) {
2860 avail = bytes;
2861 }
2862 ret = compress_write(out->compr, buffer, avail);
2863 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2864 __func__, avail, ret);
2865 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002866
Eric Laurent6e895242013-09-05 16:10:57 -07002867 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002868 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2869 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002870 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002871 compress_start(out->compr);
2872 out->playback_started = 1;
2873 out->offload_state = OFFLOAD_STATE_PLAYING;
2874 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002875 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002876 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002877 } else {
2878 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002879 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002880 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002881 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 return ret;
2883 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002884 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002886 size_t bytes_to_write = bytes;
2887
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888 if (out->muted)
2889 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002890 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02002891 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002892 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2893 int16_t *src = (int16_t *)buffer;
2894 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002895
Eric Laurentad2dde92017-09-20 18:27:31 -07002896 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2897 out->format != AUDIO_FORMAT_PCM_16_BIT,
2898 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002899
Eric Laurentad2dde92017-09-20 18:27:31 -07002900 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2901 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2902 }
2903 bytes_to_write /= 2;
2904 }
2905 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2906
Glenn Kasten5a59dff2018-02-22 08:05:35 -08002907 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002908 request_out_focus(out, ns);
2909
2910 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2911 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002912 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002913 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002914 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002915
Haynes Mathew George03c40102016-01-29 17:57:48 -08002916 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002917 } else {
2918 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002920 }
2921
2922exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002923 // For PCM we always consume the buffer and return #bytes regardless of ret.
2924 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002925 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002926 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002927 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002928
Andy Hung7401c7c2016-09-21 12:41:21 -07002929 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002930 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002931 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2932 ALOGE_IF(out->pcm != NULL,
2933 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002934 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002935 // usleep not guaranteed for values over 1 second but we don't limit here.
2936 }
2937 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939 pthread_mutex_unlock(&out->lock);
2940
2941 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002942 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002943 if (sleeptime_us != 0)
2944 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002945 }
2946 return bytes;
2947}
2948
2949static int out_get_render_position(const struct audio_stream_out *stream,
2950 uint32_t *dsp_frames)
2951{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002952 struct stream_out *out = (struct stream_out *)stream;
2953 *dsp_frames = 0;
2954 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002955 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002957 unsigned long frames = 0;
2958 // TODO: check return value
2959 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2960 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002961 ALOGVV("%s rendered frames %d sample_rate %d",
2962 __func__, *dsp_frames, out->sample_rate);
2963 }
2964 pthread_mutex_unlock(&out->lock);
2965 return 0;
2966 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002967 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968}
2969
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002970static int out_add_audio_effect(const struct audio_stream *stream __unused,
2971 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972{
2973 return 0;
2974}
2975
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002976static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2977 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978{
2979 return 0;
2980}
2981
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002982static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2983 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002984{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002985 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002986}
2987
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002988static int out_get_presentation_position(const struct audio_stream_out *stream,
2989 uint64_t *frames, struct timespec *timestamp)
2990{
2991 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002992 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002993 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002994
Eric Laurenta1478072015-09-21 17:21:52 -07002995 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002996
Eric Laurent949a0892013-09-20 09:20:13 -07002997 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2998 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002999 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07003000 compress_get_tstamp(out->compr, &dsp_frames,
3001 &out->sample_rate);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003002 // Adjustment accounts for A2DP encoder latency with offload usecases
3003 // Note: Encoder latency is returned in ms.
3004 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3005 unsigned long offset =
3006 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3007 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
3008 }
Eric Laurent949a0892013-09-20 09:20:13 -07003009 ALOGVV("%s rendered frames %ld sample_rate %d",
3010 __func__, dsp_frames, out->sample_rate);
3011 *frames = dsp_frames;
3012 ret = 0;
3013 /* this is the best we can do */
3014 clock_gettime(CLOCK_MONOTONIC, timestamp);
3015 }
3016 } else {
3017 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07003018 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07003019 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
3020 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07003021 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07003022 // This adjustment accounts for buffering after app processor.
3023 // It is based on estimated DSP latency per use case, rather than exact.
3024 signed_frames -=
3025 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
3026
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003027 // Adjustment accounts for A2DP encoder latency with non-offload usecases
3028 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
3029 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
3030 signed_frames -=
3031 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
3032 }
3033
Eric Laurent949a0892013-09-20 09:20:13 -07003034 // It would be unusual for this value to be negative, but check just in case ...
3035 if (signed_frames >= 0) {
3036 *frames = signed_frames;
3037 ret = 0;
3038 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003039 }
3040 }
3041 }
3042
3043 pthread_mutex_unlock(&out->lock);
3044
3045 return ret;
3046}
3047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048static int out_set_callback(struct audio_stream_out *stream,
3049 stream_callback_t callback, void *cookie)
3050{
3051 struct stream_out *out = (struct stream_out *)stream;
3052
3053 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003054 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003055 out->offload_callback = callback;
3056 out->offload_cookie = cookie;
3057 pthread_mutex_unlock(&out->lock);
3058 return 0;
3059}
3060
3061static int out_pause(struct audio_stream_out* stream)
3062{
3063 struct stream_out *out = (struct stream_out *)stream;
3064 int status = -ENOSYS;
3065 ALOGV("%s", __func__);
3066 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003067 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003068 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
3069 status = compress_pause(out->compr);
3070 out->offload_state = OFFLOAD_STATE_PAUSED;
3071 }
3072 pthread_mutex_unlock(&out->lock);
3073 }
3074 return status;
3075}
3076
3077static int out_resume(struct audio_stream_out* stream)
3078{
3079 struct stream_out *out = (struct stream_out *)stream;
3080 int status = -ENOSYS;
3081 ALOGV("%s", __func__);
3082 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3083 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07003084 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
3086 status = compress_resume(out->compr);
3087 out->offload_state = OFFLOAD_STATE_PLAYING;
3088 }
3089 pthread_mutex_unlock(&out->lock);
3090 }
3091 return status;
3092}
3093
3094static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
3095{
3096 struct stream_out *out = (struct stream_out *)stream;
3097 int status = -ENOSYS;
3098 ALOGV("%s", __func__);
3099 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003100 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003101 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
3102 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
3103 else
3104 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
3105 pthread_mutex_unlock(&out->lock);
3106 }
3107 return status;
3108}
3109
3110static int out_flush(struct audio_stream_out* stream)
3111{
3112 struct stream_out *out = (struct stream_out *)stream;
3113 ALOGV("%s", __func__);
3114 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07003115 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003116 stop_compressed_output_l(out);
3117 pthread_mutex_unlock(&out->lock);
3118 return 0;
3119 }
3120 return -ENOSYS;
3121}
3122
Eric Laurent0e46adf2016-12-16 12:49:24 -08003123static int out_stop(const struct audio_stream_out* stream)
3124{
3125 struct stream_out *out = (struct stream_out *)stream;
3126 struct audio_device *adev = out->dev;
3127 int ret = -ENOSYS;
3128
3129 ALOGV("%s", __func__);
3130 pthread_mutex_lock(&adev->lock);
3131 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3132 out->playback_started && out->pcm != NULL) {
3133 pcm_stop(out->pcm);
3134 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08003135 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003136 }
3137 pthread_mutex_unlock(&adev->lock);
3138 return ret;
3139}
3140
3141static int out_start(const struct audio_stream_out* stream)
3142{
3143 struct stream_out *out = (struct stream_out *)stream;
3144 struct audio_device *adev = out->dev;
3145 int ret = -ENOSYS;
3146
3147 ALOGV("%s", __func__);
3148 pthread_mutex_lock(&adev->lock);
3149 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
3150 !out->playback_started && out->pcm != NULL) {
3151 ret = start_output_stream(out);
3152 if (ret == 0) {
3153 out->playback_started = true;
3154 }
3155 }
3156 pthread_mutex_unlock(&adev->lock);
3157 return ret;
3158}
3159
Phil Burkbc991042017-02-24 08:06:44 -08003160/*
3161 * Modify config->period_count based on min_size_frames
3162 */
3163static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
3164{
3165 int periodCountRequested = (min_size_frames + config->period_size - 1)
3166 / config->period_size;
3167 int periodCount = MMAP_PERIOD_COUNT_MIN;
3168
3169 ALOGV("%s original config.period_size = %d config.period_count = %d",
3170 __func__, config->period_size, config->period_count);
3171
3172 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
3173 periodCount *= 2;
3174 }
3175 config->period_count = periodCount;
3176
3177 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
3178}
3179
Eric Laurent0e46adf2016-12-16 12:49:24 -08003180static int out_create_mmap_buffer(const struct audio_stream_out *stream,
3181 int32_t min_size_frames,
3182 struct audio_mmap_buffer_info *info)
3183{
3184 struct stream_out *out = (struct stream_out *)stream;
3185 struct audio_device *adev = out->dev;
3186 int ret = 0;
3187 unsigned int offset1;
3188 unsigned int frames1;
3189 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003190 uint32_t mmap_size;
3191 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003192
3193 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003194 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003195 pthread_mutex_lock(&adev->lock);
3196
3197 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003198 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003199 ret = -EINVAL;
3200 goto exit;
3201 }
3202 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003203 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003204 ret = -ENOSYS;
3205 goto exit;
3206 }
3207 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3208 if (out->pcm_device_id < 0) {
3209 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3210 __func__, out->pcm_device_id, out->usecase);
3211 ret = -EINVAL;
3212 goto exit;
3213 }
Phil Burkbc991042017-02-24 08:06:44 -08003214
3215 adjust_mmap_period_count(&out->config, min_size_frames);
3216
Eric Laurent0e46adf2016-12-16 12:49:24 -08003217 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3218 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3219 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3220 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3221 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3222 step = "open";
3223 ret = -ENODEV;
3224 goto exit;
3225 }
3226 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3227 if (ret < 0) {
3228 step = "begin";
3229 goto exit;
3230 }
3231 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003232 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003233 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003234 ret = platform_get_mmap_data_fd(adev->platform,
3235 out->pcm_device_id, 0 /*playback*/,
3236 &info->shared_memory_fd,
3237 &mmap_size);
3238 if (ret < 0) {
3239 // Fall back to non exclusive mode
3240 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3241 } else {
3242 if (mmap_size < buffer_size) {
3243 step = "mmap";
3244 goto exit;
3245 }
3246 // FIXME: indicate exclusive mode support by returning a negative buffer size
3247 info->buffer_size_frames *= -1;
3248 }
3249 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003250
3251 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3252 if (ret < 0) {
3253 step = "commit";
3254 goto exit;
3255 }
Phil Burkbc991042017-02-24 08:06:44 -08003256
3257 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003258 ret = 0;
3259
3260 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3261 __func__, info->shared_memory_address, info->buffer_size_frames);
3262
3263exit:
3264 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003265 if (out->pcm == NULL) {
3266 ALOGE("%s: %s - %d", __func__, step, ret);
3267 } else {
3268 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003269 pcm_close(out->pcm);
3270 out->pcm = NULL;
3271 }
3272 }
3273 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003274 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003275 return ret;
3276}
3277
3278static int out_get_mmap_position(const struct audio_stream_out *stream,
3279 struct audio_mmap_position *position)
3280{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003281 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003282 struct stream_out *out = (struct stream_out *)stream;
3283 ALOGVV("%s", __func__);
3284 if (position == NULL) {
3285 return -EINVAL;
3286 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003287 lock_output_stream(out);
3288 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3289 out->pcm == NULL) {
3290 ret = -ENOSYS;
3291 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003292 }
3293
3294 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003295 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003296 if (ret < 0) {
3297 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003298 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003299 }
Andy Hungfc044e12017-03-20 09:24:22 -07003300 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003301exit:
3302 pthread_mutex_unlock(&out->lock);
3303 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003304}
3305
3306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307/** audio_stream_in implementation **/
3308static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3309{
3310 struct stream_in *in = (struct stream_in *)stream;
3311
3312 return in->config.rate;
3313}
3314
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003315static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316{
3317 return -ENOSYS;
3318}
3319
3320static size_t in_get_buffer_size(const struct audio_stream *stream)
3321{
3322 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003323 return in->config.period_size * in->af_period_multiplier *
3324 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325}
3326
3327static uint32_t in_get_channels(const struct audio_stream *stream)
3328{
3329 struct stream_in *in = (struct stream_in *)stream;
3330
3331 return in->channel_mask;
3332}
3333
vivek mehta4ed66e62016-04-15 23:33:34 -07003334static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335{
vivek mehta4ed66e62016-04-15 23:33:34 -07003336 struct stream_in *in = (struct stream_in *)stream;
3337 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338}
3339
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003340static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341{
3342 return -ENOSYS;
3343}
3344
3345static int in_standby(struct audio_stream *stream)
3346{
3347 struct stream_in *in = (struct stream_in *)stream;
3348 struct audio_device *adev = in->dev;
3349 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003350 bool do_stop = true;
3351
Eric Laurent994a6932013-07-17 11:51:42 -07003352 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003353
3354 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003355
3356 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003357 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003358 audio_extn_sound_trigger_stop_lab(in);
3359 in->standby = true;
3360 }
3361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003363 if (adev->adm_deregister_stream)
3364 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3365
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003366 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003368 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003369 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003370 in->capture_started = false;
3371 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003372 if (in->pcm) {
3373 pcm_close(in->pcm);
3374 in->pcm = NULL;
3375 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003376 adev->enable_voicerx = false;
3377 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003378 if (do_stop) {
3379 status = stop_input_stream(in);
3380 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003381 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 }
3383 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003384 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385 return status;
3386}
3387
Andy Hungd13f0d32017-06-12 13:58:37 -07003388static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389{
Andy Hungd13f0d32017-06-12 13:58:37 -07003390 struct stream_in *in = (struct stream_in *)stream;
3391
3392 // We try to get the lock for consistency,
3393 // but it isn't necessary for these variables.
3394 // If we're not in standby, we may be blocked on a read.
3395 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3396 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3397 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3398 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3399
3400 if (locked) {
3401 pthread_mutex_unlock(&in->lock);
3402 }
3403
3404 // dump error info
3405 (void)error_log_dump(
3406 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003407 return 0;
3408}
3409
3410static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3411{
3412 struct stream_in *in = (struct stream_in *)stream;
3413 struct audio_device *adev = in->dev;
3414 struct str_parms *parms;
3415 char *str;
3416 char value[32];
3417 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003418 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419
Eric Laurent994a6932013-07-17 11:51:42 -07003420 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421 parms = str_parms_create_str(kvpairs);
3422
3423 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3424
Eric Laurenta1478072015-09-21 17:21:52 -07003425 lock_input_stream(in);
3426
Eric Laurent150dbfe2013-02-27 14:31:02 -08003427 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 if (ret >= 0) {
3429 val = atoi(value);
3430 /* no audio source uses val == 0 */
3431 if ((in->source != val) && (val != 0)) {
3432 in->source = val;
3433 }
3434 }
3435
3436 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003437
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 if (ret >= 0) {
3439 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003440 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003441
3442 // Workaround: If routing to an non existing usb device, fail gracefully
3443 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003444 int card;
3445 if (audio_is_usb_in_device(val) &&
3446 (card = get_alive_usb_card(parms)) >= 0) {
3447
3448 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003449 status = -ENOSYS;
3450 } else {
3451
3452 in->device = val;
3453 /* If recording is in progress, change the tx device to new device */
3454 if (!in->standby) {
3455 ALOGV("update input routing change");
3456 // inform adm before actual routing to prevent glitches.
3457 if (adev->adm_on_routing_change) {
3458 adev->adm_on_routing_change(adev->adm_data,
3459 in->capture_handle);
3460 }
3461 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003462 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003463 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464 }
3465 }
3466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003467 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003468 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003469
3470 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003471 ALOGV("%s: exit: status(%d)", __func__, status);
3472 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003473}
3474
Haynes Mathew George569b7482017-05-08 14:44:27 -07003475static char* in_get_parameters(const struct audio_stream *stream,
3476 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003477{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003478 struct stream_in *in = (struct stream_in *)stream;
3479 struct str_parms *query = str_parms_create_str(keys);
3480 char *str;
3481 struct str_parms *reply = str_parms_create();
3482 bool replied = false;
3483
3484 ALOGV("%s: enter: keys - %s", __func__, keys);
3485 replied |= stream_get_parameter_channels(query, reply,
3486 &in->supported_channel_masks[0]);
3487 replied |= stream_get_parameter_formats(query, reply,
3488 &in->supported_formats[0]);
3489 replied |= stream_get_parameter_rates(query, reply,
3490 &in->supported_sample_rates[0]);
3491 if (replied) {
3492 str = str_parms_to_str(reply);
3493 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003494 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003495 }
3496 str_parms_destroy(query);
3497 str_parms_destroy(reply);
3498 ALOGV("%s: exit: returns - %s", __func__, str);
3499 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003500}
3501
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003502static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003504 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003505}
3506
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003507static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3508{
3509 if (!stream || !parms)
3510 return;
3511
3512 struct stream_in *in = (struct stream_in *)stream;
3513 struct audio_device *adev = in->dev;
3514
3515 card_status_t status;
3516 int card;
3517 if (parse_snd_card_status(parms, &card, &status) < 0)
3518 return;
3519
3520 pthread_mutex_lock(&adev->lock);
3521 bool valid_cb = (card == adev->snd_card);
3522 pthread_mutex_unlock(&adev->lock);
3523
3524 if (!valid_cb)
3525 return;
3526
3527 lock_input_stream(in);
3528 if (in->card_status != status)
3529 in->card_status = status;
3530 pthread_mutex_unlock(&in->lock);
3531
3532 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3533 use_case_table[in->usecase],
3534 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3535
3536 // a better solution would be to report error back to AF and let
3537 // it put the stream to standby
3538 if (status == CARD_STATUS_OFFLINE)
3539 in_standby(&in->stream.common);
3540
3541 return;
3542}
3543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3545 size_t bytes)
3546{
3547 struct stream_in *in = (struct stream_in *)stream;
3548 struct audio_device *adev = in->dev;
3549 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003550 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003551 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552
Eric Laurenta1478072015-09-21 17:21:52 -07003553 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003554 const size_t frame_size = audio_stream_in_frame_size(stream);
3555 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003556
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003557 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003558 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003559 /* Read from sound trigger HAL */
3560 audio_extn_sound_trigger_read(in, buffer, bytes);
3561 pthread_mutex_unlock(&in->lock);
3562 return bytes;
3563 }
3564
Eric Laurent0e46adf2016-12-16 12:49:24 -08003565 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3566 ret = -ENOSYS;
3567 goto exit;
3568 }
3569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003570 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003571 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003572 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003573 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003574 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003575 goto exit;
3576 }
3577 in->standby = 0;
3578 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579
Andy Hungd13f0d32017-06-12 13:58:37 -07003580 // errors that occur here are read errors.
3581 error_code = ERROR_CODE_READ;
3582
Haynes Mathew George03c40102016-01-29 17:57:48 -08003583 //what's the duration requested by the client?
3584 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3585 in->config.rate;
3586 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003587
Haynes Mathew George03c40102016-01-29 17:57:48 -08003588 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003589 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003590 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003591 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003592 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003593 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003594 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003595 if (ret < 0) {
3596 ALOGE("Failed to read w/err %s", strerror(errno));
3597 ret = -errno;
3598 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003599 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3600 if (bytes % 4 == 0) {
3601 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3602 int_buf_stream = buffer;
3603 for (size_t itt=0; itt < bytes/4 ; itt++) {
3604 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003605 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003606 } else {
3607 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3608 ret = -EINVAL;
3609 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003610 }
3611 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612 }
3613
Haynes Mathew George03c40102016-01-29 17:57:48 -08003614 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 /*
3617 * Instead of writing zeroes here, we could trust the hardware
3618 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003619 * 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 -08003620 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003621 if (ret == 0 && adev->mic_muted &&
3622 !voice_is_in_call_rec_stream(in) &&
3623 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003624 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003625 in->frames_muted += frames;
3626 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627
3628exit:
3629 pthread_mutex_unlock(&in->lock);
3630
3631 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003632 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633 in_standby(&in->stream.common);
3634 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003635 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003636 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003637 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003638 }
3639 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003640 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003641 }
3642 return bytes;
3643}
3644
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003645static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003646{
3647 return 0;
3648}
3649
Andy Hung6ebe5962016-01-15 17:46:57 -08003650static int in_get_capture_position(const struct audio_stream_in *stream,
3651 int64_t *frames, int64_t *time)
3652{
3653 if (stream == NULL || frames == NULL || time == NULL) {
3654 return -EINVAL;
3655 }
3656 struct stream_in *in = (struct stream_in *)stream;
3657 int ret = -ENOSYS;
3658
3659 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003660 // note: ST sessions do not close the alsa pcm driver synchronously
3661 // on standby. Therefore, we may return an error even though the
3662 // pcm stream is still opened.
3663 if (in->standby) {
3664 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3665 "%s stream in standby but pcm not NULL for non ST session", __func__);
3666 goto exit;
3667 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003668 if (in->pcm) {
3669 struct timespec timestamp;
3670 unsigned int avail;
3671 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3672 *frames = in->frames_read + avail;
3673 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3674 ret = 0;
3675 }
3676 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003677exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003678 pthread_mutex_unlock(&in->lock);
3679 return ret;
3680}
3681
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003682static int add_remove_audio_effect(const struct audio_stream *stream,
3683 effect_handle_t effect,
3684 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003686 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003687 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003688 int status = 0;
3689 effect_descriptor_t desc;
3690
3691 status = (*effect)->get_descriptor(effect, &desc);
3692 if (status != 0)
3693 return status;
3694
Eric Laurenta1478072015-09-21 17:21:52 -07003695 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003696 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003697 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003698 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003699 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003700 in->enable_aec != enable &&
3701 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3702 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003703 if (!enable)
3704 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003705 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3706 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3707 adev->enable_voicerx = enable;
3708 struct audio_usecase *usecase;
3709 struct listnode *node;
3710 list_for_each(node, &adev->usecase_list) {
3711 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003712 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003713 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003714 }
3715 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003716 if (!in->standby)
3717 select_devices(in->dev, in->usecase);
3718 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003719 if (in->enable_ns != enable &&
3720 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3721 in->enable_ns = enable;
3722 if (!in->standby)
3723 select_devices(in->dev, in->usecase);
3724 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003725 pthread_mutex_unlock(&in->dev->lock);
3726 pthread_mutex_unlock(&in->lock);
3727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003728 return 0;
3729}
3730
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003731static int in_add_audio_effect(const struct audio_stream *stream,
3732 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733{
Eric Laurent994a6932013-07-17 11:51:42 -07003734 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003735 return add_remove_audio_effect(stream, effect, true);
3736}
3737
3738static int in_remove_audio_effect(const struct audio_stream *stream,
3739 effect_handle_t effect)
3740{
Eric Laurent994a6932013-07-17 11:51:42 -07003741 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003742 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743}
3744
Eric Laurent0e46adf2016-12-16 12:49:24 -08003745static int in_stop(const struct audio_stream_in* stream)
3746{
3747 struct stream_in *in = (struct stream_in *)stream;
3748 struct audio_device *adev = in->dev;
3749
3750 int ret = -ENOSYS;
3751 ALOGV("%s", __func__);
3752 pthread_mutex_lock(&adev->lock);
3753 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3754 in->capture_started && in->pcm != NULL) {
3755 pcm_stop(in->pcm);
3756 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003757 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003758 }
3759 pthread_mutex_unlock(&adev->lock);
3760 return ret;
3761}
3762
3763static int in_start(const struct audio_stream_in* stream)
3764{
3765 struct stream_in *in = (struct stream_in *)stream;
3766 struct audio_device *adev = in->dev;
3767 int ret = -ENOSYS;
3768
3769 ALOGV("%s in %p", __func__, in);
3770 pthread_mutex_lock(&adev->lock);
3771 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3772 !in->capture_started && in->pcm != NULL) {
3773 if (!in->capture_started) {
3774 ret = start_input_stream(in);
3775 if (ret == 0) {
3776 in->capture_started = true;
3777 }
3778 }
3779 }
3780 pthread_mutex_unlock(&adev->lock);
3781 return ret;
3782}
3783
3784static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3785 int32_t min_size_frames,
3786 struct audio_mmap_buffer_info *info)
3787{
3788 struct stream_in *in = (struct stream_in *)stream;
3789 struct audio_device *adev = in->dev;
3790 int ret = 0;
3791 unsigned int offset1;
3792 unsigned int frames1;
3793 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003794 uint32_t mmap_size;
3795 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003796
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003797 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003798 pthread_mutex_lock(&adev->lock);
3799 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003800
Eric Laurent0e46adf2016-12-16 12:49:24 -08003801 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003802 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003803 ret = -EINVAL;
3804 goto exit;
3805 }
3806 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003807 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003808 ALOGV("%s in %p", __func__, in);
3809 ret = -ENOSYS;
3810 goto exit;
3811 }
3812 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3813 if (in->pcm_device_id < 0) {
3814 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3815 __func__, in->pcm_device_id, in->usecase);
3816 ret = -EINVAL;
3817 goto exit;
3818 }
Phil Burkbc991042017-02-24 08:06:44 -08003819
3820 adjust_mmap_period_count(&in->config, min_size_frames);
3821
Eric Laurent0e46adf2016-12-16 12:49:24 -08003822 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3823 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3824 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3825 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3826 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3827 step = "open";
3828 ret = -ENODEV;
3829 goto exit;
3830 }
3831
3832 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3833 if (ret < 0) {
3834 step = "begin";
3835 goto exit;
3836 }
3837 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003838 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003839 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003840 ret = platform_get_mmap_data_fd(adev->platform,
3841 in->pcm_device_id, 1 /*capture*/,
3842 &info->shared_memory_fd,
3843 &mmap_size);
3844 if (ret < 0) {
3845 // Fall back to non exclusive mode
3846 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3847 } else {
3848 if (mmap_size < buffer_size) {
3849 step = "mmap";
3850 goto exit;
3851 }
3852 // FIXME: indicate exclusive mode support by returning a negative buffer size
3853 info->buffer_size_frames *= -1;
3854 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003855
Haynes Mathew George96483a22017-03-28 14:52:47 -07003856 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003857
3858 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3859 if (ret < 0) {
3860 step = "commit";
3861 goto exit;
3862 }
3863
Phil Burkbc991042017-02-24 08:06:44 -08003864 in->standby = false;
3865 ret = 0;
3866
Eric Laurent0e46adf2016-12-16 12:49:24 -08003867 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3868 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003869
3870exit:
3871 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003872 if (in->pcm == NULL) {
3873 ALOGE("%s: %s - %d", __func__, step, ret);
3874 } else {
3875 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003876 pcm_close(in->pcm);
3877 in->pcm = NULL;
3878 }
3879 }
3880 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003881 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003882 return ret;
3883}
3884
3885static int in_get_mmap_position(const struct audio_stream_in *stream,
3886 struct audio_mmap_position *position)
3887{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003888 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003889 struct stream_in *in = (struct stream_in *)stream;
3890 ALOGVV("%s", __func__);
3891 if (position == NULL) {
3892 return -EINVAL;
3893 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003894 lock_input_stream(in);
3895 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3896 in->pcm == NULL) {
3897 ret = -ENOSYS;
3898 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003899 }
3900 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003901 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003902 if (ret < 0) {
3903 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003904 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003905 }
Andy Hungfc044e12017-03-20 09:24:22 -07003906 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003907exit:
3908 pthread_mutex_unlock(&in->lock);
3909 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003910}
3911
jiabin8962a4d2018-03-19 18:21:24 -07003912static int in_get_active_microphones(const struct audio_stream_in *stream,
3913 struct audio_microphone_characteristic_t *mic_array,
3914 size_t *mic_count) {
3915 struct stream_in *in = (struct stream_in *)stream;
3916 struct audio_device *adev = in->dev;
3917 ALOGVV("%s", __func__);
3918
3919 lock_input_stream(in);
3920 pthread_mutex_lock(&adev->lock);
3921 int ret = platform_get_active_microphones(adev->platform, in->device,
3922 audio_channel_count_from_in_mask(in->channel_mask),
3923 in->source, in->usecase, mic_array, mic_count);
3924 pthread_mutex_unlock(&adev->lock);
3925 pthread_mutex_unlock(&in->lock);
3926
3927 return ret;
3928}
3929
3930static int adev_get_microphones(const struct audio_hw_device *dev,
3931 struct audio_microphone_characteristic_t *mic_array,
3932 size_t *mic_count) {
3933 struct audio_device *adev = (struct audio_device *)dev;
3934 ALOGVV("%s", __func__);
3935
3936 pthread_mutex_lock(&adev->lock);
3937 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
3938 pthread_mutex_unlock(&adev->lock);
3939
3940 return ret;
3941}
Eric Laurent0e46adf2016-12-16 12:49:24 -08003942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003943static int adev_open_output_stream(struct audio_hw_device *dev,
3944 audio_io_handle_t handle,
3945 audio_devices_t devices,
3946 audio_output_flags_t flags,
3947 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003948 struct audio_stream_out **stream_out,
3949 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950{
3951 struct audio_device *adev = (struct audio_device *)dev;
3952 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003953 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003954 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3955 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3956 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957
Andy Hungd9653bd2017-08-01 19:31:39 -07003958 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3959 return -ENOSYS;
3960 }
3961
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003962 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3963 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003964 *stream_out = NULL;
3965 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3966
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003967 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
3968
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003969 if (devices == AUDIO_DEVICE_NONE)
3970 devices = AUDIO_DEVICE_OUT_SPEAKER;
3971
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003972 out->flags = flags;
3973 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003974 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003975 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003976 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003977 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978
3979 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003980 if ((is_hdmi || is_usb_dev) &&
3981 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3982 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3983 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07003984 audio_format_t req_format = config->format;
3985 audio_channel_mask_t req_channel_mask = config->channel_mask;
3986 uint32_t req_sample_rate = config->sample_rate;
3987
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003988 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003989 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003990 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003991 if (config->sample_rate == 0)
3992 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07003993 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07003994 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3995 if (config->format == AUDIO_FORMAT_DEFAULT)
3996 config->format = AUDIO_FORMAT_PCM_16_BIT;
3997 } else if (is_usb_dev) {
3998 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3999 &config->format,
4000 &out->supported_formats[0],
4001 MAX_SUPPORTED_FORMATS,
4002 &config->channel_mask,
4003 &out->supported_channel_masks[0],
4004 MAX_SUPPORTED_CHANNEL_MASKS,
4005 &config->sample_rate,
4006 &out->supported_sample_rates[0],
4007 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004008 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004009 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004010 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07004011 if (ret != 0) {
4012 // For MMAP NO IRQ, allow conversions in ADSP
4013 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
4014 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004015
Eric Laurentab805ee2018-03-30 12:20:38 -07004016 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
4017 config->sample_rate = req_sample_rate;
4018 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
4019 config->channel_mask = req_channel_mask;
4020 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
4021 config->format = req_format;
4022 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004023
Haynes Mathew George569b7482017-05-08 14:44:27 -07004024 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004025 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004026 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004027 if (is_hdmi) {
4028 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4029 out->config = pcm_config_hdmi_multi;
4030 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4031 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4032 out->config = pcm_config_mmap_playback;
4033 out->stream.start = out_start;
4034 out->stream.stop = out_stop;
4035 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4036 out->stream.get_mmap_position = out_get_mmap_position;
4037 } else {
4038 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4039 out->config = pcm_config_hifi;
4040 }
4041
4042 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004043 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004044 if (is_hdmi) {
4045 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4046 audio_bytes_per_sample(out->format));
4047 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004048 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004049 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004050 pthread_mutex_lock(&adev->lock);
4051 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4052 pthread_mutex_unlock(&adev->lock);
4053
4054 // reject offload during card offline to allow
4055 // fallback to s/w paths
4056 if (offline) {
4057 ret = -ENODEV;
4058 goto error_open;
4059 }
4060
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004061 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4062 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4063 ALOGE("%s: Unsupported Offload information", __func__);
4064 ret = -EINVAL;
4065 goto error_open;
4066 }
4067 if (!is_supported_format(config->offload_info.format)) {
4068 ALOGE("%s: Unsupported audio format", __func__);
4069 ret = -EINVAL;
4070 goto error_open;
4071 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004072 out->sample_rate = config->offload_info.sample_rate;
4073 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4074 out->channel_mask = config->offload_info.channel_mask;
4075 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4076 out->channel_mask = config->channel_mask;
4077 else
4078 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4079
4080 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004081
4082 out->compr_config.codec = (struct snd_codec *)
4083 calloc(1, sizeof(struct snd_codec));
4084
4085 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004086
4087 out->stream.set_callback = out_set_callback;
4088 out->stream.pause = out_pause;
4089 out->stream.resume = out_resume;
4090 out->stream.drain = out_drain;
4091 out->stream.flush = out_flush;
4092
4093 out->compr_config.codec->id =
4094 get_snd_codec_id(config->offload_info.format);
4095 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4096 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004097 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004098 out->compr_config.codec->bit_rate =
4099 config->offload_info.bit_rate;
4100 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004101 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004102 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4103
4104 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4105 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004106
4107 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004108 create_offload_callback_thread(out);
4109 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4110 __func__, config->offload_info.version,
4111 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004112 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4113 switch (config->sample_rate) {
4114 case 0:
4115 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4116 break;
4117 case 8000:
4118 case 16000:
4119 case 48000:
4120 out->sample_rate = config->sample_rate;
4121 break;
4122 default:
4123 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4124 config->sample_rate);
4125 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4126 ret = -EINVAL;
4127 goto error_open;
4128 }
4129 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4130 switch (config->channel_mask) {
4131 case AUDIO_CHANNEL_NONE:
4132 case AUDIO_CHANNEL_OUT_STEREO:
4133 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4134 break;
4135 default:
4136 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4137 config->channel_mask);
4138 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4139 ret = -EINVAL;
4140 goto error_open;
4141 }
4142 switch (config->format) {
4143 case AUDIO_FORMAT_DEFAULT:
4144 case AUDIO_FORMAT_PCM_16_BIT:
4145 out->format = AUDIO_FORMAT_PCM_16_BIT;
4146 break;
4147 default:
4148 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4149 config->format);
4150 config->format = AUDIO_FORMAT_PCM_16_BIT;
4151 ret = -EINVAL;
4152 goto error_open;
4153 }
4154
4155 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004156 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004157 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004158 case 0:
4159 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4160 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004161 case 8000:
4162 case 16000:
4163 case 48000:
4164 out->sample_rate = config->sample_rate;
4165 break;
4166 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004167 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4168 config->sample_rate);
4169 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4170 ret = -EINVAL;
4171 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004172 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004173 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4174 switch (config->channel_mask) {
4175 case AUDIO_CHANNEL_NONE:
4176 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4177 break;
4178 case AUDIO_CHANNEL_OUT_STEREO:
4179 out->channel_mask = config->channel_mask;
4180 break;
4181 default:
4182 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4183 config->channel_mask);
4184 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4185 ret = -EINVAL;
4186 break;
4187 }
4188 switch (config->format) {
4189 case AUDIO_FORMAT_DEFAULT:
4190 out->format = AUDIO_FORMAT_PCM_16_BIT;
4191 break;
4192 case AUDIO_FORMAT_PCM_16_BIT:
4193 out->format = config->format;
4194 break;
4195 default:
4196 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4197 config->format);
4198 config->format = AUDIO_FORMAT_PCM_16_BIT;
4199 ret = -EINVAL;
4200 break;
4201 }
4202 if (ret != 0)
4203 goto error_open;
4204
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004205 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4206 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004207 out->config.rate = out->sample_rate;
4208 out->config.channels =
4209 audio_channel_count_from_out_mask(out->channel_mask);
4210 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004211 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004212 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4213 switch (config->sample_rate) {
4214 case 0:
4215 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4216 break;
4217 case 8000:
4218 case 16000:
4219 case 32000:
4220 case 48000:
4221 out->sample_rate = config->sample_rate;
4222 break;
4223 default:
4224 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4225 config->sample_rate);
4226 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4227 ret = -EINVAL;
4228 break;
4229 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004230 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004231 switch (config->channel_mask) {
4232 case AUDIO_CHANNEL_NONE:
4233 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4234 break;
4235 case AUDIO_CHANNEL_OUT_STEREO:
4236 out->channel_mask = config->channel_mask;
4237 break;
4238 default:
4239 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4240 config->channel_mask);
4241 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4242 ret = -EINVAL;
4243 break;
4244 }
4245 switch (config->format) {
4246 case AUDIO_FORMAT_DEFAULT:
4247 out->format = AUDIO_FORMAT_PCM_16_BIT;
4248 break;
4249 case AUDIO_FORMAT_PCM_16_BIT:
4250 out->format = config->format;
4251 break;
4252 default:
4253 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4254 config->format);
4255 config->format = AUDIO_FORMAT_PCM_16_BIT;
4256 ret = -EINVAL;
4257 break;
4258 }
4259 if (ret != 0)
4260 goto error_open;
4261
vivek mehtaa68fea62017-06-08 19:04:02 -07004262 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004263 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4264 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004265 out->config.rate = out->sample_rate;
4266 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004267 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004268 out->sample_rate,
4269 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004270 out->config.channels,
4271 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004272 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004273 out->config.period_size = buffer_size / frame_size;
4274 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4275 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004276 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004277 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004278 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4279 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004280 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004281 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4282 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004283 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004284 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004285 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004286 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004287 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004288 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4289 out->config = pcm_config_mmap_playback;
4290 out->stream.start = out_start;
4291 out->stream.stop = out_stop;
4292 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4293 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004294 } else {
4295 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4296 out->config = pcm_config_low_latency;
4297 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004298
4299 if (config->sample_rate == 0) {
4300 out->sample_rate = out->config.rate;
4301 } else {
4302 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004303 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004304 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4305 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4306 } else {
4307 out->channel_mask = config->channel_mask;
4308 }
4309 if (config->format == AUDIO_FORMAT_DEFAULT)
4310 out->format = audio_format_from_pcm_format(out->config.format);
4311 else if (!audio_is_linear_pcm(config->format)) {
4312 config->format = AUDIO_FORMAT_PCM_16_BIT;
4313 ret = -EINVAL;
4314 goto error_open;
4315 } else {
4316 out->format = config->format;
4317 }
4318
4319 out->config.rate = out->sample_rate;
4320 out->config.channels =
4321 audio_channel_count_from_out_mask(out->channel_mask);
4322 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4323 out->config.format = pcm_format_from_audio_format(out->format);
4324 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004325 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004326
4327 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4328 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004329 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004330 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4331 __func__, config->sample_rate, config->format, config->channel_mask);
4332 config->sample_rate = out->sample_rate;
4333 config->format = out->format;
4334 config->channel_mask = out->channel_mask;
4335 ret = -EINVAL;
4336 goto error_open;
4337 }
4338
Andy Hung6fcba9c2014-03-18 11:53:32 -07004339 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4340 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004342 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004343 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004344 adev->primary_output = out;
4345 else {
4346 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004347 ret = -EEXIST;
4348 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004349 }
4350 }
4351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352 /* Check if this usecase is already existing */
4353 pthread_mutex_lock(&adev->lock);
4354 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4355 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004357 ret = -EEXIST;
4358 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004359 }
4360 pthread_mutex_unlock(&adev->lock);
4361
4362 out->stream.common.get_sample_rate = out_get_sample_rate;
4363 out->stream.common.set_sample_rate = out_set_sample_rate;
4364 out->stream.common.get_buffer_size = out_get_buffer_size;
4365 out->stream.common.get_channels = out_get_channels;
4366 out->stream.common.get_format = out_get_format;
4367 out->stream.common.set_format = out_set_format;
4368 out->stream.common.standby = out_standby;
4369 out->stream.common.dump = out_dump;
4370 out->stream.common.set_parameters = out_set_parameters;
4371 out->stream.common.get_parameters = out_get_parameters;
4372 out->stream.common.add_audio_effect = out_add_audio_effect;
4373 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4374 out->stream.get_latency = out_get_latency;
4375 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004376#ifdef NO_AUDIO_OUT
4377 out->stream.write = out_write_for_no_output;
4378#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004380#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381 out->stream.get_render_position = out_get_render_position;
4382 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004383 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004384
Eric Laurent0e46adf2016-12-16 12:49:24 -08004385 if (out->realtime)
4386 out->af_period_multiplier = af_period_multiplier;
4387 else
4388 out->af_period_multiplier = 1;
4389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004391 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004392 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004394 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004395 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004396 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4397
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004398 config->format = out->stream.common.get_format(&out->stream.common);
4399 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4400 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4401
Andy Hunga452b0a2017-03-15 14:51:15 -07004402 out->error_log = error_log_create(
4403 ERROR_LOG_ENTRIES,
4404 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4405
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004406 /*
4407 By locking output stream before registering, we allow the callback
4408 to update stream's state only after stream's initial state is set to
4409 adev state.
4410 */
4411 lock_output_stream(out);
4412 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4413 pthread_mutex_lock(&adev->lock);
4414 out->card_status = adev->card_status;
4415 pthread_mutex_unlock(&adev->lock);
4416 pthread_mutex_unlock(&out->lock);
4417
vivek mehta4a824772017-06-08 19:05:49 -07004418 stream_app_type_cfg_init(&out->app_type_cfg);
4419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004421
Eric Laurent994a6932013-07-17 11:51:42 -07004422 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004424
4425error_open:
4426 free(out);
4427 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004428 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004429 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430}
4431
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004432static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004433 struct audio_stream_out *stream)
4434{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004435 struct stream_out *out = (struct stream_out *)stream;
4436 struct audio_device *adev = out->dev;
4437
Eric Laurent994a6932013-07-17 11:51:42 -07004438 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004439
4440 // must deregister from sndmonitor first to prevent races
4441 // between the callback and close_stream
4442 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004444 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4445 destroy_offload_callback_thread(out);
4446
4447 if (out->compr_config.codec != NULL)
4448 free(out->compr_config.codec);
4449 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004450
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004451 out->a2dp_compress_mute = false;
4452
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004453 if (adev->voice_tx_output == out)
4454 adev->voice_tx_output = NULL;
4455
Andy Hunga452b0a2017-03-15 14:51:15 -07004456 error_log_destroy(out->error_log);
4457 out->error_log = NULL;
4458
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004459 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004460 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004461 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004462 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004463 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004464}
4465
4466static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4467{
4468 struct audio_device *adev = (struct audio_device *)dev;
4469 struct str_parms *parms;
4470 char *str;
4471 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004472 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004473 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004474 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475
Joe Onorato188b6222016-03-01 11:02:27 -08004476 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004477
4478 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004479
4480 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004481 status = voice_set_parameters(adev, parms);
4482 if (status != 0) {
4483 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004484 }
4485
4486 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4487 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004488 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004489 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4490 adev->bluetooth_nrec = true;
4491 else
4492 adev->bluetooth_nrec = false;
4493 }
4494
4495 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4496 if (ret >= 0) {
4497 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4498 adev->screen_off = false;
4499 else
4500 adev->screen_off = true;
4501 }
4502
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004503 ret = str_parms_get_int(parms, "rotation", &val);
4504 if (ret >= 0) {
4505 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004506 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004507 // FIXME: note that the code below assumes that the speakers are in the correct placement
4508 // relative to the user when the device is rotated 90deg from its default rotation. This
4509 // assumption is device-specific, not platform-specific like this code.
4510 case 270:
4511 reverse_speakers = true;
4512 break;
4513 case 0:
4514 case 90:
4515 case 180:
4516 break;
4517 default:
4518 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004519 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004520 }
Eric Laurent03f09432014-03-25 18:09:11 -07004521 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004522 // check and set swap
4523 // - check if orientation changed and speaker active
4524 // - set rotation and cache the rotation value
4525 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004526 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004527 }
4528
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004529 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4530 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004531 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004532 }
4533
David Linee3fe402017-03-13 10:00:42 -07004534 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4535 if (ret >= 0) {
4536 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004537 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004538 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4539 if (ret >= 0) {
4540 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004541 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004542 }
Eric Laurent99dab492017-06-17 15:19:08 -07004543 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004544 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4545 if (ret >= 0) {
4546 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004547 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004548 }
4549 }
4550 }
4551
4552 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4553 if (ret >= 0) {
4554 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004555 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004556 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4557 if (ret >= 0) {
4558 const int card = atoi(value);
4559
Eric Laurent99dab492017-06-17 15:19:08 -07004560 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004561 }
Eric Laurent99dab492017-06-17 15:19:08 -07004562 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004563 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4564 if (ret >= 0) {
4565 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004566 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004567 }
4568 }
4569 }
4570
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004571 audio_extn_hfp_set_parameters(adev, parms);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004572 audio_extn_a2dp_set_parameters(parms);
4573 // reconfigure should be done only after updating A2DP state in audio extension
4574 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4575 if (ret >= 0) {
4576 struct audio_usecase *usecase;
4577 struct listnode *node;
4578 list_for_each(node, &adev->usecase_list) {
4579 usecase = node_to_item(node, struct audio_usecase, list);
4580 if ((usecase->type == PCM_PLAYBACK) &&
4581 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
4582 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4583
4584 pthread_mutex_unlock(&adev->lock);
4585 lock_output_stream(usecase->stream.out);
4586 pthread_mutex_lock(&adev->lock);
4587 audio_extn_a2dp_set_handoff_mode(true);
4588 // force device switch to reconfigure encoder
4589 select_devices(adev, usecase->id);
4590 audio_extn_a2dp_set_handoff_mode(false);
4591 pthread_mutex_unlock(&usecase->stream.out->lock);
4592 break;
4593 }
4594 }
4595 }
4596
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004597done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004598 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004599 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004600 ALOGV("%s: exit with code(%d)", __func__, status);
4601 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004602}
4603
4604static char* adev_get_parameters(const struct audio_hw_device *dev,
4605 const char *keys)
4606{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004607 struct audio_device *adev = (struct audio_device *)dev;
4608 struct str_parms *reply = str_parms_create();
4609 struct str_parms *query = str_parms_create_str(keys);
4610 char *str;
4611
4612 pthread_mutex_lock(&adev->lock);
4613
4614 voice_get_parameters(adev, query, reply);
4615 str = str_parms_to_str(reply);
4616 str_parms_destroy(query);
4617 str_parms_destroy(reply);
4618
4619 pthread_mutex_unlock(&adev->lock);
4620 ALOGV("%s: exit: returns - %s", __func__, str);
4621 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622}
4623
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004624static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004625{
4626 return 0;
4627}
4628
Haynes Mathew George5191a852013-09-11 14:19:36 -07004629static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4630{
4631 int ret;
4632 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004633
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004634 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4635
Haynes Mathew George5191a852013-09-11 14:19:36 -07004636 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004637 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004638 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004639
Haynes Mathew George5191a852013-09-11 14:19:36 -07004640 return ret;
4641}
4642
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004643static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644{
4645 return -ENOSYS;
4646}
4647
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004648static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4649 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650{
4651 return -ENOSYS;
4652}
4653
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004654static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004655{
4656 return -ENOSYS;
4657}
4658
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004659static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004660{
4661 return -ENOSYS;
4662}
4663
4664static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4665{
4666 struct audio_device *adev = (struct audio_device *)dev;
4667
4668 pthread_mutex_lock(&adev->lock);
4669 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004670 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004672 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4673 voice_is_in_call(adev)) {
4674 voice_stop_call(adev);
4675 adev->current_call_output = NULL;
4676 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004677 }
4678 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004679
4680 audio_extn_extspk_set_mode(adev->extspk, mode);
4681
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004682 return 0;
4683}
4684
4685static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4686{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004687 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004688 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004689
Eric Laurent2bafff12016-03-17 12:17:23 -07004690 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004691 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004692 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4693 ret = audio_extn_hfp_set_mic_mute(adev, state);
4694 } else {
4695 ret = voice_set_mic_mute(adev, state);
4696 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004697 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004698 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004699
4700 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004701}
4702
4703static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4704{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004705 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004706 return 0;
4707}
4708
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004709static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004710 const struct audio_config *config)
4711{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004712 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004713
Eric Laurent74b55762017-07-09 17:04:53 -07004714 /* Don't know if USB HIFI in this context so use true to be conservative */
4715 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4716 true /*is_usb_hifi */) != 0)
4717 return 0;
4718
vivek mehtaa68fea62017-06-08 19:04:02 -07004719 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4720 config->sample_rate, config->format,
4721 channel_count,
4722 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004723}
4724
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004725static bool adev_input_allow_hifi_record(struct audio_device *adev,
4726 audio_devices_t devices,
4727 audio_input_flags_t flags,
4728 audio_source_t source) {
4729 const bool allowed = true;
4730
4731 if (!audio_is_usb_in_device(devices))
4732 return !allowed;
4733
4734 switch (flags) {
4735 case AUDIO_INPUT_FLAG_NONE:
4736 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4737 break;
4738 default:
4739 return !allowed;
4740 }
4741
4742 switch (source) {
4743 case AUDIO_SOURCE_DEFAULT:
4744 case AUDIO_SOURCE_MIC:
4745 case AUDIO_SOURCE_UNPROCESSED:
4746 break;
4747 default:
4748 return !allowed;
4749 }
4750
4751 switch (adev->mode) {
4752 case 0:
4753 break;
4754 default:
4755 return !allowed;
4756 }
4757
4758 return allowed;
4759}
4760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004761static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004762 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763 audio_devices_t devices,
4764 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004765 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004766 audio_input_flags_t flags,
4767 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004768 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004769{
4770 struct audio_device *adev = (struct audio_device *)dev;
4771 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004772 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004773 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004774 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004775 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004776 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4777 devices,
4778 flags,
4779 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004780 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004781 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004782
Andy Hungd9653bd2017-08-01 19:31:39 -07004783 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4784 return -ENOSYS;
4785 }
4786
Eric Laurent74b55762017-07-09 17:04:53 -07004787 if (!(is_usb_dev && may_use_hifi_record)) {
4788 if (config->sample_rate == 0)
4789 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4790 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4791 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4792 if (config->format == AUDIO_FORMAT_DEFAULT)
4793 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004794
Eric Laurent74b55762017-07-09 17:04:53 -07004795 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4796
4797 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4798 return -EINVAL;
4799 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004801 if (audio_extn_tfa_98xx_is_supported() &&
4802 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004803 return -EINVAL;
4804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004805 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4806
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004807 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004808 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004810 in->stream.common.get_sample_rate = in_get_sample_rate;
4811 in->stream.common.set_sample_rate = in_set_sample_rate;
4812 in->stream.common.get_buffer_size = in_get_buffer_size;
4813 in->stream.common.get_channels = in_get_channels;
4814 in->stream.common.get_format = in_get_format;
4815 in->stream.common.set_format = in_set_format;
4816 in->stream.common.standby = in_standby;
4817 in->stream.common.dump = in_dump;
4818 in->stream.common.set_parameters = in_set_parameters;
4819 in->stream.common.get_parameters = in_get_parameters;
4820 in->stream.common.add_audio_effect = in_add_audio_effect;
4821 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4822 in->stream.set_gain = in_set_gain;
4823 in->stream.read = in_read;
4824 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004825 in->stream.get_capture_position = in_get_capture_position;
jiabin8962a4d2018-03-19 18:21:24 -07004826 in->stream.get_active_microphones = in_get_active_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004827
4828 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004829 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004830 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004831 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004832 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004833 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004834
Haynes Mathew George569b7482017-05-08 14:44:27 -07004835 if (is_usb_dev && may_use_hifi_record) {
4836 /* HiFi record selects an appropriate format, channel, rate combo
4837 depending on sink capabilities*/
4838 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4839 &config->format,
4840 &in->supported_formats[0],
4841 MAX_SUPPORTED_FORMATS,
4842 &config->channel_mask,
4843 &in->supported_channel_masks[0],
4844 MAX_SUPPORTED_CHANNEL_MASKS,
4845 &config->sample_rate,
4846 &in->supported_sample_rates[0],
4847 MAX_SUPPORTED_SAMPLE_RATES);
4848 if (ret != 0) {
4849 ret = -EINVAL;
4850 goto err_open;
4851 }
Eric Laurent74b55762017-07-09 17:04:53 -07004852 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004853 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004854 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004855 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4856 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4857 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4858 bool ret_error = false;
4859 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4860 from HAL is 8_24
4861 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4862 8_24 return error indicating supported format is 8_24
4863 *> In case of any other source requesting 24 bit or float return error
4864 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004865
vivek mehta57ff9b52016-04-28 14:13:08 -07004866 on error flinger will retry with supported format passed
4867 */
4868 if (source != AUDIO_SOURCE_UNPROCESSED) {
4869 config->format = AUDIO_FORMAT_PCM_16_BIT;
4870 ret_error = true;
4871 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4872 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4873 ret_error = true;
4874 }
4875
4876 if (ret_error) {
4877 ret = -EINVAL;
4878 goto err_open;
4879 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004880 }
4881
vivek mehta57ff9b52016-04-28 14:13:08 -07004882 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004883 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004884
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004886 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4887 if (config->sample_rate == 0)
4888 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4889 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4890 config->sample_rate != 8000) {
4891 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4892 ret = -EINVAL;
4893 goto err_open;
4894 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004895
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004896 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4897 config->format = AUDIO_FORMAT_PCM_16_BIT;
4898 ret = -EINVAL;
4899 goto err_open;
4900 }
4901
4902 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4903 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004904 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004905 } else if (is_usb_dev && may_use_hifi_record) {
4906 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4907 in->config = pcm_config_audio_capture;
4908 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004909 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4910 config->sample_rate,
4911 config->format,
4912 channel_count,
4913 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004914 in->config.period_size = buffer_size / frame_size;
4915 in->config.rate = config->sample_rate;
4916 in->af_period_multiplier = 1;
4917 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004918 } else {
4919 in->usecase = USECASE_AUDIO_RECORD;
4920 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004921 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004922 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004923#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004924 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004925#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004926 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004927 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004928 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004929 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004930 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4931 config->sample_rate,
4932 config->format,
4933 channel_count,
4934 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004935 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004936 in->config.rate = config->sample_rate;
4937 in->af_period_multiplier = 1;
4938 } else {
4939 // period size is left untouched for rt mode playback
4940 in->config = pcm_config_audio_capture_rt;
4941 in->af_period_multiplier = af_period_multiplier;
4942 }
4943 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4944 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004945 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004946 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4947 in->config = pcm_config_mmap_capture;
4948 in->stream.start = in_start;
4949 in->stream.stop = in_stop;
4950 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4951 in->stream.get_mmap_position = in_get_mmap_position;
4952 in->af_period_multiplier = 1;
4953 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004954 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004955 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004956 (config->sample_rate == 8000 ||
4957 config->sample_rate == 16000 ||
4958 config->sample_rate == 32000 ||
4959 config->sample_rate == 48000) &&
4960 channel_count == 1) {
4961 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4962 in->config = pcm_config_audio_capture;
4963 frame_size = audio_stream_in_frame_size(&in->stream);
4964 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4965 config->sample_rate,
4966 config->format,
4967 channel_count, false /*is_low_latency*/);
4968 in->config.period_size = buffer_size / frame_size;
4969 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4970 in->config.rate = config->sample_rate;
4971 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004972 } else {
4973 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004974 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004975 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4976 config->sample_rate,
4977 config->format,
4978 channel_count,
4979 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004980 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004981 in->config.rate = config->sample_rate;
4982 in->af_period_multiplier = 1;
4983 }
4984 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4985 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004986 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004988 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004989 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004990
Andy Hungd13f0d32017-06-12 13:58:37 -07004991 in->error_log = error_log_create(
4992 ERROR_LOG_ENTRIES,
4993 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4994
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004995 /* This stream could be for sound trigger lab,
4996 get sound trigger pcm if present */
4997 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004998
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004999 lock_input_stream(in);
5000 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
5001 pthread_mutex_lock(&adev->lock);
5002 in->card_status = adev->card_status;
5003 pthread_mutex_unlock(&adev->lock);
5004 pthread_mutex_unlock(&in->lock);
5005
vivek mehta4a824772017-06-08 19:05:49 -07005006 stream_app_type_cfg_init(&in->app_type_cfg);
5007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005008 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005009 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005010 return 0;
5011
5012err_open:
5013 free(in);
5014 *stream_in = NULL;
5015 return ret;
5016}
5017
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005018static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005019 struct audio_stream_in *stream)
5020{
Andy Hungd13f0d32017-06-12 13:58:37 -07005021 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07005022 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08005023
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005024 // must deregister from sndmonitor first to prevent races
5025 // between the callback and close_stream
5026 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005027 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07005028
5029 error_log_destroy(in->error_log);
5030 in->error_log = NULL;
5031
Andy Hung0dbb52b2017-08-09 13:51:38 -07005032 pthread_mutex_destroy(&in->pre_lock);
5033 pthread_mutex_destroy(&in->lock);
5034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005035 free(stream);
5036
5037 return;
5038}
5039
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005040static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005041{
5042 return 0;
5043}
5044
Andy Hung31aca912014-03-20 17:14:59 -07005045/* verifies input and output devices and their capabilities.
5046 *
5047 * This verification is required when enabling extended bit-depth or
5048 * sampling rates, as not all qcom products support it.
5049 *
5050 * Suitable for calling only on initialization such as adev_open().
5051 * It fills the audio_device use_case_table[] array.
5052 *
5053 * Has a side-effect that it needs to configure audio routing / devices
5054 * in order to power up the devices and read the device parameters.
5055 * It does not acquire any hw device lock. Should restore the devices
5056 * back to "normal state" upon completion.
5057 */
5058static int adev_verify_devices(struct audio_device *adev)
5059{
5060 /* enumeration is a bit difficult because one really wants to pull
5061 * the use_case, device id, etc from the hidden pcm_device_table[].
5062 * In this case there are the following use cases and device ids.
5063 *
5064 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5065 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005066 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005067 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5068 * [USECASE_AUDIO_RECORD] = {0, 0},
5069 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5070 * [USECASE_VOICE_CALL] = {2, 2},
5071 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005072 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005073 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5074 */
5075
5076 /* should be the usecases enabled in adev_open_input_stream() */
5077 static const int test_in_usecases[] = {
5078 USECASE_AUDIO_RECORD,
5079 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5080 };
5081 /* should be the usecases enabled in adev_open_output_stream()*/
5082 static const int test_out_usecases[] = {
5083 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5084 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5085 };
5086 static const usecase_type_t usecase_type_by_dir[] = {
5087 PCM_PLAYBACK,
5088 PCM_CAPTURE,
5089 };
5090 static const unsigned flags_by_dir[] = {
5091 PCM_OUT,
5092 PCM_IN,
5093 };
5094
5095 size_t i;
5096 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005097 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005098 char info[512]; /* for possible debug info */
5099
5100 for (dir = 0; dir < 2; ++dir) {
5101 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5102 const unsigned flags_dir = flags_by_dir[dir];
5103 const size_t testsize =
5104 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5105 const int *testcases =
5106 dir ? test_in_usecases : test_out_usecases;
5107 const audio_devices_t audio_device =
5108 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5109
5110 for (i = 0; i < testsize; ++i) {
5111 const audio_usecase_t audio_usecase = testcases[i];
5112 int device_id;
5113 snd_device_t snd_device;
5114 struct pcm_params **pparams;
5115 struct stream_out out;
5116 struct stream_in in;
5117 struct audio_usecase uc_info;
5118 int retval;
5119
5120 pparams = &adev->use_case_table[audio_usecase];
5121 pcm_params_free(*pparams); /* can accept null input */
5122 *pparams = NULL;
5123
5124 /* find the device ID for the use case (signed, for error) */
5125 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5126 if (device_id < 0)
5127 continue;
5128
5129 /* prepare structures for device probing */
5130 memset(&uc_info, 0, sizeof(uc_info));
5131 uc_info.id = audio_usecase;
5132 uc_info.type = usecase_type;
5133 if (dir) {
5134 adev->active_input = &in;
5135 memset(&in, 0, sizeof(in));
5136 in.device = audio_device;
5137 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5138 uc_info.stream.in = &in;
5139 } else {
5140 adev->active_input = NULL;
5141 }
5142 memset(&out, 0, sizeof(out));
5143 out.devices = audio_device; /* only field needed in select_devices */
5144 uc_info.stream.out = &out;
5145 uc_info.devices = audio_device;
5146 uc_info.in_snd_device = SND_DEVICE_NONE;
5147 uc_info.out_snd_device = SND_DEVICE_NONE;
5148 list_add_tail(&adev->usecase_list, &uc_info.list);
5149
5150 /* select device - similar to start_(in/out)put_stream() */
5151 retval = select_devices(adev, audio_usecase);
5152 if (retval >= 0) {
5153 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5154#if LOG_NDEBUG == 0
5155 if (*pparams) {
5156 ALOGV("%s: (%s) card %d device %d", __func__,
5157 dir ? "input" : "output", card_id, device_id);
5158 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005159 } else {
5160 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5161 }
5162#endif
5163 }
5164
5165 /* deselect device - similar to stop_(in/out)put_stream() */
5166 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005167 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005168 /* 2. Disable the rx device */
5169 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005170 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005171 list_remove(&uc_info.list);
5172 }
5173 }
5174 adev->active_input = NULL; /* restore adev state */
5175 return 0;
5176}
5177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005178static int adev_close(hw_device_t *device)
5179{
Andy Hung31aca912014-03-20 17:14:59 -07005180 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005181 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005182
5183 if (!adev)
5184 return 0;
5185
5186 pthread_mutex_lock(&adev_init_lock);
5187
5188 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005189 audio_extn_snd_mon_unregister_listener(adev);
5190 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005191 audio_route_free(adev->audio_route);
5192 free(adev->snd_dev_ref_cnt);
5193 platform_deinit(adev->platform);
5194 audio_extn_extspk_deinit(adev->extspk);
5195 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005196 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005197 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5198 pcm_params_free(adev->use_case_table[i]);
5199 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005200 if (adev->adm_deinit)
5201 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005202 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005203 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005204 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005205
5206 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005208 return 0;
5209}
5210
Glenn Kasten4f993392014-05-14 07:30:48 -07005211/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5212 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5213 * just that it _might_ work.
5214 */
5215static int period_size_is_plausible_for_low_latency(int period_size)
5216{
5217 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005218 case 48:
5219 case 96:
5220 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005221 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005222 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005223 case 240:
5224 case 320:
5225 case 480:
5226 return 1;
5227 default:
5228 return 0;
5229 }
5230}
5231
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005232static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5233{
5234 int card;
5235 card_status_t status;
5236
5237 if (!parms)
5238 return;
5239
5240 if (parse_snd_card_status(parms, &card, &status) < 0)
5241 return;
5242
5243 pthread_mutex_lock(&adev->lock);
5244 bool valid_cb = (card == adev->snd_card);
5245 if (valid_cb) {
5246 if (adev->card_status != status) {
5247 adev->card_status = status;
5248 platform_snd_card_update(adev->platform, status);
5249 }
5250 }
5251 pthread_mutex_unlock(&adev->lock);
5252 return;
5253}
5254
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005255/* out and adev lock held */
5256static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5257{
5258 struct audio_usecase *uc_info;
5259 float left_p;
5260 float right_p;
5261 audio_devices_t devices;
5262
5263 uc_info = get_usecase_from_list(adev, out->usecase);
5264 if (uc_info == NULL) {
5265 ALOGE("%s: Could not find the usecase (%d) in the list",
5266 __func__, out->usecase);
5267 return -EINVAL;
5268 }
5269
5270 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5271 out->usecase, use_case_table[out->usecase]);
5272
5273 if (restore) {
5274 // restore A2DP device for active usecases and unmute if required
5275 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5276 !is_a2dp_device(uc_info->out_snd_device)) {
5277 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5278 select_devices(adev, uc_info->id);
5279 pthread_mutex_lock(&out->compr_mute_lock);
5280 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5281 (out->a2dp_compress_mute)) {
5282 out->a2dp_compress_mute = false;
5283 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5284 }
5285 pthread_mutex_unlock(&out->compr_mute_lock);
5286 }
5287 } else {
5288 // mute compress stream if suspended
5289 pthread_mutex_lock(&out->compr_mute_lock);
5290 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5291 (!out->a2dp_compress_mute)) {
5292 if (!out->standby) {
5293 ALOGD("%s: selecting speaker and muting stream", __func__);
5294 devices = out->devices;
5295 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5296 left_p = out->volume_l;
5297 right_p = out->volume_r;
5298 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5299 compress_pause(out->compr);
5300 set_compr_volume(&out->stream, 0.0f, 0.0f);
5301 out->a2dp_compress_mute = true;
5302 select_devices(adev, out->usecase);
5303 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5304 compress_resume(out->compr);
5305 out->devices = devices;
5306 out->volume_l = left_p;
5307 out->volume_r = right_p;
5308 }
5309 }
5310 pthread_mutex_unlock(&out->compr_mute_lock);
5311 }
5312 ALOGV("%s: exit", __func__);
5313 return 0;
5314}
5315
5316int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5317{
5318 int ret = 0;
5319
5320 lock_output_stream(out);
5321 pthread_mutex_lock(&adev->lock);
5322
5323 ret = check_a2dp_restore_l(adev, out, restore);
5324
5325 pthread_mutex_unlock(&adev->lock);
5326 pthread_mutex_unlock(&out->lock);
5327 return ret;
5328}
5329
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005330static int adev_open(const hw_module_t *module, const char *name,
5331 hw_device_t **device)
5332{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005333 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005334
Eric Laurent2bafff12016-03-17 12:17:23 -07005335 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005336 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005337 pthread_mutex_lock(&adev_init_lock);
5338 if (audio_device_ref_count != 0) {
5339 *device = &adev->device.common;
5340 audio_device_ref_count++;
5341 ALOGV("%s: returning existing instance of adev", __func__);
5342 ALOGV("%s: exit", __func__);
5343 pthread_mutex_unlock(&adev_init_lock);
5344 return 0;
5345 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005346 adev = calloc(1, sizeof(struct audio_device));
5347
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005348 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5349
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005350 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5351 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5352 adev->device.common.module = (struct hw_module_t *)module;
5353 adev->device.common.close = adev_close;
5354
5355 adev->device.init_check = adev_init_check;
5356 adev->device.set_voice_volume = adev_set_voice_volume;
5357 adev->device.set_master_volume = adev_set_master_volume;
5358 adev->device.get_master_volume = adev_get_master_volume;
5359 adev->device.set_master_mute = adev_set_master_mute;
5360 adev->device.get_master_mute = adev_get_master_mute;
5361 adev->device.set_mode = adev_set_mode;
5362 adev->device.set_mic_mute = adev_set_mic_mute;
5363 adev->device.get_mic_mute = adev_get_mic_mute;
5364 adev->device.set_parameters = adev_set_parameters;
5365 adev->device.get_parameters = adev_get_parameters;
5366 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5367 adev->device.open_output_stream = adev_open_output_stream;
5368 adev->device.close_output_stream = adev_close_output_stream;
5369 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005371 adev->device.close_input_stream = adev_close_input_stream;
5372 adev->device.dump = adev_dump;
jiabin8962a4d2018-03-19 18:21:24 -07005373 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005374
5375 /* Set the default route before the PCM stream is opened */
5376 pthread_mutex_lock(&adev->lock);
5377 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005378 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005379 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005380 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005381 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005382 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005383 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005384 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005385 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005386 pthread_mutex_unlock(&adev->lock);
5387
5388 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005389 adev->platform = platform_init(adev);
5390 if (!adev->platform) {
5391 free(adev->snd_dev_ref_cnt);
5392 free(adev);
5393 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5394 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005395 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005396 return -EINVAL;
5397 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005398 adev->extspk = audio_extn_extspk_init(adev);
5399
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005400 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5401 if (adev->visualizer_lib == NULL) {
5402 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5403 } else {
5404 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5405 adev->visualizer_start_output =
5406 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5407 "visualizer_hal_start_output");
5408 adev->visualizer_stop_output =
5409 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5410 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005411 }
5412
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005413 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5414 if (adev->offload_effects_lib == NULL) {
5415 ALOGW("%s: DLOPEN failed for %s", __func__,
5416 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5417 } else {
5418 ALOGV("%s: DLOPEN successful for %s", __func__,
5419 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5420 adev->offload_effects_start_output =
5421 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5422 "offload_effects_bundle_hal_start_output");
5423 adev->offload_effects_stop_output =
5424 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5425 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005426 }
5427
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005428 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5429 if (adev->adm_lib == NULL) {
5430 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5431 } else {
5432 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5433 adev->adm_init = (adm_init_t)
5434 dlsym(adev->adm_lib, "adm_init");
5435 adev->adm_deinit = (adm_deinit_t)
5436 dlsym(adev->adm_lib, "adm_deinit");
5437 adev->adm_register_input_stream = (adm_register_input_stream_t)
5438 dlsym(adev->adm_lib, "adm_register_input_stream");
5439 adev->adm_register_output_stream = (adm_register_output_stream_t)
5440 dlsym(adev->adm_lib, "adm_register_output_stream");
5441 adev->adm_deregister_stream = (adm_deregister_stream_t)
5442 dlsym(adev->adm_lib, "adm_deregister_stream");
5443 adev->adm_request_focus = (adm_request_focus_t)
5444 dlsym(adev->adm_lib, "adm_request_focus");
5445 adev->adm_abandon_focus = (adm_abandon_focus_t)
5446 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005447 adev->adm_set_config = (adm_set_config_t)
5448 dlsym(adev->adm_lib, "adm_set_config");
5449 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5450 dlsym(adev->adm_lib, "adm_request_focus_v2");
5451 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5452 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5453 adev->adm_on_routing_change = (adm_on_routing_change_t)
5454 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005455 }
5456
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005457 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005458 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005459
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005460 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005461
Andy Hung31aca912014-03-20 17:14:59 -07005462 if (k_enable_extended_precision)
5463 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005464
Glenn Kasten4f993392014-05-14 07:30:48 -07005465 char value[PROPERTY_VALUE_MAX];
5466 int trial;
5467 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5468 trial = atoi(value);
5469 if (period_size_is_plausible_for_low_latency(trial)) {
5470 pcm_config_low_latency.period_size = trial;
5471 pcm_config_low_latency.start_threshold = trial / 4;
5472 pcm_config_low_latency.avail_min = trial / 4;
5473 configured_low_latency_capture_period_size = trial;
5474 }
5475 }
5476 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5477 trial = atoi(value);
5478 if (period_size_is_plausible_for_low_latency(trial)) {
5479 configured_low_latency_capture_period_size = trial;
5480 }
5481 }
5482
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005483 // commented as full set of app type cfg is sent from platform
5484 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005485 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005486
5487 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5488 af_period_multiplier = atoi(value);
5489 if (af_period_multiplier < 0) {
5490 af_period_multiplier = 2;
5491 } else if (af_period_multiplier > 4) {
5492 af_period_multiplier = 4;
5493 }
5494 ALOGV("new period_multiplier = %d", af_period_multiplier);
5495 }
5496
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005497 audio_extn_tfa_98xx_init(adev);
5498
vivek mehta1a9b7c02015-06-25 11:49:38 -07005499 pthread_mutex_unlock(&adev_init_lock);
5500
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005501 if (adev->adm_init)
5502 adev->adm_data = adev->adm_init();
5503
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005504 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005505 audio_extn_snd_mon_init();
5506 pthread_mutex_lock(&adev->lock);
5507 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5508 adev->card_status = CARD_STATUS_ONLINE;
5509 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005510 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005511
Eric Laurent2bafff12016-03-17 12:17:23 -07005512 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005513 return 0;
5514}
5515
5516static struct hw_module_methods_t hal_module_methods = {
5517 .open = adev_open,
5518};
5519
5520struct audio_module HAL_MODULE_INFO_SYM = {
5521 .common = {
5522 .tag = HARDWARE_MODULE_TAG,
5523 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5524 .hal_api_version = HARDWARE_HAL_API_VERSION,
5525 .id = AUDIO_HARDWARE_MODULE_ID,
5526 .name = "QCOM Audio HAL",
5527 .author = "Code Aurora Forum",
5528 .methods = &hal_module_methods,
5529 },
5530};