blob: dfde0a8e4022ab75a32a7fb0a313845d1dff7151 [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
3912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913static int adev_open_output_stream(struct audio_hw_device *dev,
3914 audio_io_handle_t handle,
3915 audio_devices_t devices,
3916 audio_output_flags_t flags,
3917 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003918 struct audio_stream_out **stream_out,
3919 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003920{
3921 struct audio_device *adev = (struct audio_device *)dev;
3922 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003923 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003924 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3925 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3926 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927
Andy Hungd9653bd2017-08-01 19:31:39 -07003928 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3929 return -ENOSYS;
3930 }
3931
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003932 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3933 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934 *stream_out = NULL;
3935 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3936
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003937 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
3938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003939 if (devices == AUDIO_DEVICE_NONE)
3940 devices = AUDIO_DEVICE_OUT_SPEAKER;
3941
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003942 out->flags = flags;
3943 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003944 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003945 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003946 out->handle = handle;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08003947 out->a2dp_compress_mute = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003948
3949 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003950 if ((is_hdmi || is_usb_dev) &&
3951 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3952 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3953 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Eric Laurentab805ee2018-03-30 12:20:38 -07003954 audio_format_t req_format = config->format;
3955 audio_channel_mask_t req_channel_mask = config->channel_mask;
3956 uint32_t req_sample_rate = config->sample_rate;
3957
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003958 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003959 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003960 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003961 if (config->sample_rate == 0)
3962 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Eric Laurentab805ee2018-03-30 12:20:38 -07003963 if (config->channel_mask == AUDIO_CHANNEL_NONE)
Haynes Mathew George569b7482017-05-08 14:44:27 -07003964 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3965 if (config->format == AUDIO_FORMAT_DEFAULT)
3966 config->format = AUDIO_FORMAT_PCM_16_BIT;
3967 } else if (is_usb_dev) {
3968 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3969 &config->format,
3970 &out->supported_formats[0],
3971 MAX_SUPPORTED_FORMATS,
3972 &config->channel_mask,
3973 &out->supported_channel_masks[0],
3974 MAX_SUPPORTED_CHANNEL_MASKS,
3975 &config->sample_rate,
3976 &out->supported_sample_rates[0],
3977 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003978 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003979 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003980 pthread_mutex_unlock(&adev->lock);
Eric Laurentab805ee2018-03-30 12:20:38 -07003981 if (ret != 0) {
3982 // For MMAP NO IRQ, allow conversions in ADSP
3983 if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
3984 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003985
Eric Laurentab805ee2018-03-30 12:20:38 -07003986 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
3987 config->sample_rate = req_sample_rate;
3988 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
3989 config->channel_mask = req_channel_mask;
3990 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
3991 config->format = req_format;
3992 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003993
Haynes Mathew George569b7482017-05-08 14:44:27 -07003994 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003995 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003996 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003997 if (is_hdmi) {
3998 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3999 out->config = pcm_config_hdmi_multi;
4000 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
4001 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4002 out->config = pcm_config_mmap_playback;
4003 out->stream.start = out_start;
4004 out->stream.stop = out_stop;
4005 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4006 out->stream.get_mmap_position = out_get_mmap_position;
4007 } else {
4008 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
4009 out->config = pcm_config_hifi;
4010 }
4011
4012 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004013 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004014 if (is_hdmi) {
4015 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4016 audio_bytes_per_sample(out->format));
4017 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004018 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004019 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004020 pthread_mutex_lock(&adev->lock);
4021 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4022 pthread_mutex_unlock(&adev->lock);
4023
4024 // reject offload during card offline to allow
4025 // fallback to s/w paths
4026 if (offline) {
4027 ret = -ENODEV;
4028 goto error_open;
4029 }
4030
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004031 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4032 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4033 ALOGE("%s: Unsupported Offload information", __func__);
4034 ret = -EINVAL;
4035 goto error_open;
4036 }
4037 if (!is_supported_format(config->offload_info.format)) {
4038 ALOGE("%s: Unsupported audio format", __func__);
4039 ret = -EINVAL;
4040 goto error_open;
4041 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004042 out->sample_rate = config->offload_info.sample_rate;
4043 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4044 out->channel_mask = config->offload_info.channel_mask;
4045 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4046 out->channel_mask = config->channel_mask;
4047 else
4048 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4049
4050 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004051
4052 out->compr_config.codec = (struct snd_codec *)
4053 calloc(1, sizeof(struct snd_codec));
4054
4055 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004056
4057 out->stream.set_callback = out_set_callback;
4058 out->stream.pause = out_pause;
4059 out->stream.resume = out_resume;
4060 out->stream.drain = out_drain;
4061 out->stream.flush = out_flush;
4062
4063 out->compr_config.codec->id =
4064 get_snd_codec_id(config->offload_info.format);
4065 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4066 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004067 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004068 out->compr_config.codec->bit_rate =
4069 config->offload_info.bit_rate;
4070 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004071 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004072 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4073
4074 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4075 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004076
4077 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004078 create_offload_callback_thread(out);
4079 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4080 __func__, config->offload_info.version,
4081 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004082 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4083 switch (config->sample_rate) {
4084 case 0:
4085 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4086 break;
4087 case 8000:
4088 case 16000:
4089 case 48000:
4090 out->sample_rate = config->sample_rate;
4091 break;
4092 default:
4093 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4094 config->sample_rate);
4095 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4096 ret = -EINVAL;
4097 goto error_open;
4098 }
4099 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4100 switch (config->channel_mask) {
4101 case AUDIO_CHANNEL_NONE:
4102 case AUDIO_CHANNEL_OUT_STEREO:
4103 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4104 break;
4105 default:
4106 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4107 config->channel_mask);
4108 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4109 ret = -EINVAL;
4110 goto error_open;
4111 }
4112 switch (config->format) {
4113 case AUDIO_FORMAT_DEFAULT:
4114 case AUDIO_FORMAT_PCM_16_BIT:
4115 out->format = AUDIO_FORMAT_PCM_16_BIT;
4116 break;
4117 default:
4118 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4119 config->format);
4120 config->format = AUDIO_FORMAT_PCM_16_BIT;
4121 ret = -EINVAL;
4122 goto error_open;
4123 }
4124
4125 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004126 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004127 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004128 case 0:
4129 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4130 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004131 case 8000:
4132 case 16000:
4133 case 48000:
4134 out->sample_rate = config->sample_rate;
4135 break;
4136 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004137 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4138 config->sample_rate);
4139 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4140 ret = -EINVAL;
4141 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004142 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004143 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4144 switch (config->channel_mask) {
4145 case AUDIO_CHANNEL_NONE:
4146 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4147 break;
4148 case AUDIO_CHANNEL_OUT_STEREO:
4149 out->channel_mask = config->channel_mask;
4150 break;
4151 default:
4152 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4153 config->channel_mask);
4154 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4155 ret = -EINVAL;
4156 break;
4157 }
4158 switch (config->format) {
4159 case AUDIO_FORMAT_DEFAULT:
4160 out->format = AUDIO_FORMAT_PCM_16_BIT;
4161 break;
4162 case AUDIO_FORMAT_PCM_16_BIT:
4163 out->format = config->format;
4164 break;
4165 default:
4166 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4167 config->format);
4168 config->format = AUDIO_FORMAT_PCM_16_BIT;
4169 ret = -EINVAL;
4170 break;
4171 }
4172 if (ret != 0)
4173 goto error_open;
4174
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004175 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4176 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004177 out->config.rate = out->sample_rate;
4178 out->config.channels =
4179 audio_channel_count_from_out_mask(out->channel_mask);
4180 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004181 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004182 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4183 switch (config->sample_rate) {
4184 case 0:
4185 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4186 break;
4187 case 8000:
4188 case 16000:
4189 case 32000:
4190 case 48000:
4191 out->sample_rate = config->sample_rate;
4192 break;
4193 default:
4194 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4195 config->sample_rate);
4196 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4197 ret = -EINVAL;
4198 break;
4199 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004200 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004201 switch (config->channel_mask) {
4202 case AUDIO_CHANNEL_NONE:
4203 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4204 break;
4205 case AUDIO_CHANNEL_OUT_STEREO:
4206 out->channel_mask = config->channel_mask;
4207 break;
4208 default:
4209 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4210 config->channel_mask);
4211 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4212 ret = -EINVAL;
4213 break;
4214 }
4215 switch (config->format) {
4216 case AUDIO_FORMAT_DEFAULT:
4217 out->format = AUDIO_FORMAT_PCM_16_BIT;
4218 break;
4219 case AUDIO_FORMAT_PCM_16_BIT:
4220 out->format = config->format;
4221 break;
4222 default:
4223 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4224 config->format);
4225 config->format = AUDIO_FORMAT_PCM_16_BIT;
4226 ret = -EINVAL;
4227 break;
4228 }
4229 if (ret != 0)
4230 goto error_open;
4231
vivek mehtaa68fea62017-06-08 19:04:02 -07004232 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004233 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4234 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004235 out->config.rate = out->sample_rate;
4236 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004237 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004238 out->sample_rate,
4239 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004240 out->config.channels,
4241 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004242 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004243 out->config.period_size = buffer_size / frame_size;
4244 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4245 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004247 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004248 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4249 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004250 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004251 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4252 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004253 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004254 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004255 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004256 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004257 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004258 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4259 out->config = pcm_config_mmap_playback;
4260 out->stream.start = out_start;
4261 out->stream.stop = out_stop;
4262 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4263 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004264 } else {
4265 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4266 out->config = pcm_config_low_latency;
4267 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004268
4269 if (config->sample_rate == 0) {
4270 out->sample_rate = out->config.rate;
4271 } else {
4272 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004273 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004274 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4275 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4276 } else {
4277 out->channel_mask = config->channel_mask;
4278 }
4279 if (config->format == AUDIO_FORMAT_DEFAULT)
4280 out->format = audio_format_from_pcm_format(out->config.format);
4281 else if (!audio_is_linear_pcm(config->format)) {
4282 config->format = AUDIO_FORMAT_PCM_16_BIT;
4283 ret = -EINVAL;
4284 goto error_open;
4285 } else {
4286 out->format = config->format;
4287 }
4288
4289 out->config.rate = out->sample_rate;
4290 out->config.channels =
4291 audio_channel_count_from_out_mask(out->channel_mask);
4292 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4293 out->config.format = pcm_format_from_audio_format(out->format);
4294 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004295 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004296
4297 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4298 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004299 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004300 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4301 __func__, config->sample_rate, config->format, config->channel_mask);
4302 config->sample_rate = out->sample_rate;
4303 config->format = out->format;
4304 config->channel_mask = out->channel_mask;
4305 ret = -EINVAL;
4306 goto error_open;
4307 }
4308
Andy Hung6fcba9c2014-03-18 11:53:32 -07004309 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4310 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004311
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004312 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004313 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004314 adev->primary_output = out;
4315 else {
4316 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004317 ret = -EEXIST;
4318 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004319 }
4320 }
4321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322 /* Check if this usecase is already existing */
4323 pthread_mutex_lock(&adev->lock);
4324 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4325 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004327 ret = -EEXIST;
4328 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329 }
4330 pthread_mutex_unlock(&adev->lock);
4331
4332 out->stream.common.get_sample_rate = out_get_sample_rate;
4333 out->stream.common.set_sample_rate = out_set_sample_rate;
4334 out->stream.common.get_buffer_size = out_get_buffer_size;
4335 out->stream.common.get_channels = out_get_channels;
4336 out->stream.common.get_format = out_get_format;
4337 out->stream.common.set_format = out_set_format;
4338 out->stream.common.standby = out_standby;
4339 out->stream.common.dump = out_dump;
4340 out->stream.common.set_parameters = out_set_parameters;
4341 out->stream.common.get_parameters = out_get_parameters;
4342 out->stream.common.add_audio_effect = out_add_audio_effect;
4343 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4344 out->stream.get_latency = out_get_latency;
4345 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004346#ifdef NO_AUDIO_OUT
4347 out->stream.write = out_write_for_no_output;
4348#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004349 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004350#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004351 out->stream.get_render_position = out_get_render_position;
4352 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004353 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354
Eric Laurent0e46adf2016-12-16 12:49:24 -08004355 if (out->realtime)
4356 out->af_period_multiplier = af_period_multiplier;
4357 else
4358 out->af_period_multiplier = 1;
4359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004361 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004362 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004363
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004364 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004365 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004366 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368 config->format = out->stream.common.get_format(&out->stream.common);
4369 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4370 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4371
Andy Hunga452b0a2017-03-15 14:51:15 -07004372 out->error_log = error_log_create(
4373 ERROR_LOG_ENTRIES,
4374 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4375
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004376 /*
4377 By locking output stream before registering, we allow the callback
4378 to update stream's state only after stream's initial state is set to
4379 adev state.
4380 */
4381 lock_output_stream(out);
4382 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4383 pthread_mutex_lock(&adev->lock);
4384 out->card_status = adev->card_status;
4385 pthread_mutex_unlock(&adev->lock);
4386 pthread_mutex_unlock(&out->lock);
4387
vivek mehta4a824772017-06-08 19:05:49 -07004388 stream_app_type_cfg_init(&out->app_type_cfg);
4389
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004391
Eric Laurent994a6932013-07-17 11:51:42 -07004392 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004394
4395error_open:
4396 free(out);
4397 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004398 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004399 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400}
4401
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004402static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403 struct audio_stream_out *stream)
4404{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004405 struct stream_out *out = (struct stream_out *)stream;
4406 struct audio_device *adev = out->dev;
4407
Eric Laurent994a6932013-07-17 11:51:42 -07004408 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004409
4410 // must deregister from sndmonitor first to prevent races
4411 // between the callback and close_stream
4412 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004414 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4415 destroy_offload_callback_thread(out);
4416
4417 if (out->compr_config.codec != NULL)
4418 free(out->compr_config.codec);
4419 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004420
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004421 out->a2dp_compress_mute = false;
4422
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004423 if (adev->voice_tx_output == out)
4424 adev->voice_tx_output = NULL;
4425
Andy Hunga452b0a2017-03-15 14:51:15 -07004426 error_log_destroy(out->error_log);
4427 out->error_log = NULL;
4428
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004429 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004430 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004431 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004433 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434}
4435
4436static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4437{
4438 struct audio_device *adev = (struct audio_device *)dev;
4439 struct str_parms *parms;
4440 char *str;
4441 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004442 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004443 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004444 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004445
Joe Onorato188b6222016-03-01 11:02:27 -08004446 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004447
4448 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004449
4450 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004451 status = voice_set_parameters(adev, parms);
4452 if (status != 0) {
4453 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454 }
4455
4456 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4457 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004458 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4460 adev->bluetooth_nrec = true;
4461 else
4462 adev->bluetooth_nrec = false;
4463 }
4464
4465 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4466 if (ret >= 0) {
4467 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4468 adev->screen_off = false;
4469 else
4470 adev->screen_off = true;
4471 }
4472
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004473 ret = str_parms_get_int(parms, "rotation", &val);
4474 if (ret >= 0) {
4475 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004476 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004477 // FIXME: note that the code below assumes that the speakers are in the correct placement
4478 // relative to the user when the device is rotated 90deg from its default rotation. This
4479 // assumption is device-specific, not platform-specific like this code.
4480 case 270:
4481 reverse_speakers = true;
4482 break;
4483 case 0:
4484 case 90:
4485 case 180:
4486 break;
4487 default:
4488 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004489 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004490 }
Eric Laurent03f09432014-03-25 18:09:11 -07004491 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004492 // check and set swap
4493 // - check if orientation changed and speaker active
4494 // - set rotation and cache the rotation value
4495 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004496 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004497 }
4498
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004499 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4500 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004501 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004502 }
4503
David Linee3fe402017-03-13 10:00:42 -07004504 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4505 if (ret >= 0) {
4506 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004507 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004508 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4509 if (ret >= 0) {
4510 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004511 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004512 }
Eric Laurent99dab492017-06-17 15:19:08 -07004513 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004514 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4515 if (ret >= 0) {
4516 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004517 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004518 }
4519 }
4520 }
4521
4522 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4523 if (ret >= 0) {
4524 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004525 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004526 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4527 if (ret >= 0) {
4528 const int card = atoi(value);
4529
Eric Laurent99dab492017-06-17 15:19:08 -07004530 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004531 }
Eric Laurent99dab492017-06-17 15:19:08 -07004532 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004533 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4534 if (ret >= 0) {
4535 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004536 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004537 }
4538 }
4539 }
4540
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004541 audio_extn_hfp_set_parameters(adev, parms);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004542 audio_extn_a2dp_set_parameters(parms);
4543 // reconfigure should be done only after updating A2DP state in audio extension
4544 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4545 if (ret >= 0) {
4546 struct audio_usecase *usecase;
4547 struct listnode *node;
4548 list_for_each(node, &adev->usecase_list) {
4549 usecase = node_to_item(node, struct audio_usecase, list);
4550 if ((usecase->type == PCM_PLAYBACK) &&
4551 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
4552 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4553
4554 pthread_mutex_unlock(&adev->lock);
4555 lock_output_stream(usecase->stream.out);
4556 pthread_mutex_lock(&adev->lock);
4557 audio_extn_a2dp_set_handoff_mode(true);
4558 // force device switch to reconfigure encoder
4559 select_devices(adev, usecase->id);
4560 audio_extn_a2dp_set_handoff_mode(false);
4561 pthread_mutex_unlock(&usecase->stream.out->lock);
4562 break;
4563 }
4564 }
4565 }
4566
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004567done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004568 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004569 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004570 ALOGV("%s: exit with code(%d)", __func__, status);
4571 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572}
4573
4574static char* adev_get_parameters(const struct audio_hw_device *dev,
4575 const char *keys)
4576{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004577 struct audio_device *adev = (struct audio_device *)dev;
4578 struct str_parms *reply = str_parms_create();
4579 struct str_parms *query = str_parms_create_str(keys);
4580 char *str;
4581
4582 pthread_mutex_lock(&adev->lock);
4583
4584 voice_get_parameters(adev, query, reply);
4585 str = str_parms_to_str(reply);
4586 str_parms_destroy(query);
4587 str_parms_destroy(reply);
4588
4589 pthread_mutex_unlock(&adev->lock);
4590 ALOGV("%s: exit: returns - %s", __func__, str);
4591 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004592}
4593
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004594static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004595{
4596 return 0;
4597}
4598
Haynes Mathew George5191a852013-09-11 14:19:36 -07004599static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4600{
4601 int ret;
4602 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004603
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004604 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4605
Haynes Mathew George5191a852013-09-11 14:19:36 -07004606 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004607 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004608 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004609
Haynes Mathew George5191a852013-09-11 14:19:36 -07004610 return ret;
4611}
4612
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004613static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614{
4615 return -ENOSYS;
4616}
4617
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004618static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4619 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620{
4621 return -ENOSYS;
4622}
4623
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004624static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004625{
4626 return -ENOSYS;
4627}
4628
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004629static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004630{
4631 return -ENOSYS;
4632}
4633
4634static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4635{
4636 struct audio_device *adev = (struct audio_device *)dev;
4637
4638 pthread_mutex_lock(&adev->lock);
4639 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004640 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004641 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004642 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4643 voice_is_in_call(adev)) {
4644 voice_stop_call(adev);
4645 adev->current_call_output = NULL;
4646 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004647 }
4648 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004649
4650 audio_extn_extspk_set_mode(adev->extspk, mode);
4651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004652 return 0;
4653}
4654
4655static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4656{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004657 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004658 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004659
Eric Laurent2bafff12016-03-17 12:17:23 -07004660 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004661 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004662 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4663 ret = audio_extn_hfp_set_mic_mute(adev, state);
4664 } else {
4665 ret = voice_set_mic_mute(adev, state);
4666 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004667 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004668 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004669
4670 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671}
4672
4673static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4674{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004675 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004676 return 0;
4677}
4678
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004679static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004680 const struct audio_config *config)
4681{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004682 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004683
Eric Laurent74b55762017-07-09 17:04:53 -07004684 /* Don't know if USB HIFI in this context so use true to be conservative */
4685 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4686 true /*is_usb_hifi */) != 0)
4687 return 0;
4688
vivek mehtaa68fea62017-06-08 19:04:02 -07004689 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4690 config->sample_rate, config->format,
4691 channel_count,
4692 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004693}
4694
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004695static bool adev_input_allow_hifi_record(struct audio_device *adev,
4696 audio_devices_t devices,
4697 audio_input_flags_t flags,
4698 audio_source_t source) {
4699 const bool allowed = true;
4700
4701 if (!audio_is_usb_in_device(devices))
4702 return !allowed;
4703
4704 switch (flags) {
4705 case AUDIO_INPUT_FLAG_NONE:
4706 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4707 break;
4708 default:
4709 return !allowed;
4710 }
4711
4712 switch (source) {
4713 case AUDIO_SOURCE_DEFAULT:
4714 case AUDIO_SOURCE_MIC:
4715 case AUDIO_SOURCE_UNPROCESSED:
4716 break;
4717 default:
4718 return !allowed;
4719 }
4720
4721 switch (adev->mode) {
4722 case 0:
4723 break;
4724 default:
4725 return !allowed;
4726 }
4727
4728 return allowed;
4729}
4730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004731static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004732 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004733 audio_devices_t devices,
4734 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004735 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004736 audio_input_flags_t flags,
4737 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004738 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004739{
4740 struct audio_device *adev = (struct audio_device *)dev;
4741 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004742 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004743 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004744 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004745 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004746 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4747 devices,
4748 flags,
4749 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004750 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004751 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004752
Andy Hungd9653bd2017-08-01 19:31:39 -07004753 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4754 return -ENOSYS;
4755 }
4756
Eric Laurent74b55762017-07-09 17:04:53 -07004757 if (!(is_usb_dev && may_use_hifi_record)) {
4758 if (config->sample_rate == 0)
4759 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4760 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4761 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4762 if (config->format == AUDIO_FORMAT_DEFAULT)
4763 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004764
Eric Laurent74b55762017-07-09 17:04:53 -07004765 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4766
4767 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4768 return -EINVAL;
4769 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004770
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004771 if (audio_extn_tfa_98xx_is_supported() &&
4772 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004773 return -EINVAL;
4774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004775 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4776
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004777 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004778 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004780 in->stream.common.get_sample_rate = in_get_sample_rate;
4781 in->stream.common.set_sample_rate = in_set_sample_rate;
4782 in->stream.common.get_buffer_size = in_get_buffer_size;
4783 in->stream.common.get_channels = in_get_channels;
4784 in->stream.common.get_format = in_get_format;
4785 in->stream.common.set_format = in_set_format;
4786 in->stream.common.standby = in_standby;
4787 in->stream.common.dump = in_dump;
4788 in->stream.common.set_parameters = in_set_parameters;
4789 in->stream.common.get_parameters = in_get_parameters;
4790 in->stream.common.add_audio_effect = in_add_audio_effect;
4791 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4792 in->stream.set_gain = in_set_gain;
4793 in->stream.read = in_read;
4794 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004795 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796
4797 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004798 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004799 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004801 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004802 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004803
Haynes Mathew George569b7482017-05-08 14:44:27 -07004804 if (is_usb_dev && may_use_hifi_record) {
4805 /* HiFi record selects an appropriate format, channel, rate combo
4806 depending on sink capabilities*/
4807 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4808 &config->format,
4809 &in->supported_formats[0],
4810 MAX_SUPPORTED_FORMATS,
4811 &config->channel_mask,
4812 &in->supported_channel_masks[0],
4813 MAX_SUPPORTED_CHANNEL_MASKS,
4814 &config->sample_rate,
4815 &in->supported_sample_rates[0],
4816 MAX_SUPPORTED_SAMPLE_RATES);
4817 if (ret != 0) {
4818 ret = -EINVAL;
4819 goto err_open;
4820 }
Eric Laurent74b55762017-07-09 17:04:53 -07004821 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004822 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004823 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004824 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4825 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4826 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4827 bool ret_error = false;
4828 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4829 from HAL is 8_24
4830 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4831 8_24 return error indicating supported format is 8_24
4832 *> In case of any other source requesting 24 bit or float return error
4833 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004834
vivek mehta57ff9b52016-04-28 14:13:08 -07004835 on error flinger will retry with supported format passed
4836 */
4837 if (source != AUDIO_SOURCE_UNPROCESSED) {
4838 config->format = AUDIO_FORMAT_PCM_16_BIT;
4839 ret_error = true;
4840 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4841 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4842 ret_error = true;
4843 }
4844
4845 if (ret_error) {
4846 ret = -EINVAL;
4847 goto err_open;
4848 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004849 }
4850
vivek mehta57ff9b52016-04-28 14:13:08 -07004851 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004852 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004853
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004854 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004855 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4856 if (config->sample_rate == 0)
4857 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4858 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4859 config->sample_rate != 8000) {
4860 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4861 ret = -EINVAL;
4862 goto err_open;
4863 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004864
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004865 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4866 config->format = AUDIO_FORMAT_PCM_16_BIT;
4867 ret = -EINVAL;
4868 goto err_open;
4869 }
4870
4871 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4872 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004873 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004874 } else if (is_usb_dev && may_use_hifi_record) {
4875 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4876 in->config = pcm_config_audio_capture;
4877 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004878 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4879 config->sample_rate,
4880 config->format,
4881 channel_count,
4882 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004883 in->config.period_size = buffer_size / frame_size;
4884 in->config.rate = config->sample_rate;
4885 in->af_period_multiplier = 1;
4886 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004887 } else {
4888 in->usecase = USECASE_AUDIO_RECORD;
4889 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004890 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004891 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004892#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004893 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004894#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004895 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004896 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004897 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004898 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004899 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4900 config->sample_rate,
4901 config->format,
4902 channel_count,
4903 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004904 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004905 in->config.rate = config->sample_rate;
4906 in->af_period_multiplier = 1;
4907 } else {
4908 // period size is left untouched for rt mode playback
4909 in->config = pcm_config_audio_capture_rt;
4910 in->af_period_multiplier = af_period_multiplier;
4911 }
4912 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4913 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004914 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004915 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4916 in->config = pcm_config_mmap_capture;
4917 in->stream.start = in_start;
4918 in->stream.stop = in_stop;
4919 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4920 in->stream.get_mmap_position = in_get_mmap_position;
4921 in->af_period_multiplier = 1;
4922 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004923 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004924 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004925 (config->sample_rate == 8000 ||
4926 config->sample_rate == 16000 ||
4927 config->sample_rate == 32000 ||
4928 config->sample_rate == 48000) &&
4929 channel_count == 1) {
4930 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4931 in->config = pcm_config_audio_capture;
4932 frame_size = audio_stream_in_frame_size(&in->stream);
4933 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4934 config->sample_rate,
4935 config->format,
4936 channel_count, false /*is_low_latency*/);
4937 in->config.period_size = buffer_size / frame_size;
4938 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4939 in->config.rate = config->sample_rate;
4940 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004941 } else {
4942 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004943 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004944 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4945 config->sample_rate,
4946 config->format,
4947 channel_count,
4948 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004949 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004950 in->config.rate = config->sample_rate;
4951 in->af_period_multiplier = 1;
4952 }
4953 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4954 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004955 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004956
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004957 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004958 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004959
Andy Hungd13f0d32017-06-12 13:58:37 -07004960 in->error_log = error_log_create(
4961 ERROR_LOG_ENTRIES,
4962 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4963
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004964 /* This stream could be for sound trigger lab,
4965 get sound trigger pcm if present */
4966 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004967
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004968 lock_input_stream(in);
4969 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4970 pthread_mutex_lock(&adev->lock);
4971 in->card_status = adev->card_status;
4972 pthread_mutex_unlock(&adev->lock);
4973 pthread_mutex_unlock(&in->lock);
4974
vivek mehta4a824772017-06-08 19:05:49 -07004975 stream_app_type_cfg_init(&in->app_type_cfg);
4976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004977 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004978 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979 return 0;
4980
4981err_open:
4982 free(in);
4983 *stream_in = NULL;
4984 return ret;
4985}
4986
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004987static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004988 struct audio_stream_in *stream)
4989{
Andy Hungd13f0d32017-06-12 13:58:37 -07004990 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004991 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004992
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004993 // must deregister from sndmonitor first to prevent races
4994 // between the callback and close_stream
4995 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004996 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004997
4998 error_log_destroy(in->error_log);
4999 in->error_log = NULL;
5000
Andy Hung0dbb52b2017-08-09 13:51:38 -07005001 pthread_mutex_destroy(&in->pre_lock);
5002 pthread_mutex_destroy(&in->lock);
5003
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005004 free(stream);
5005
5006 return;
5007}
5008
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07005009static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005010{
5011 return 0;
5012}
5013
Andy Hung31aca912014-03-20 17:14:59 -07005014/* verifies input and output devices and their capabilities.
5015 *
5016 * This verification is required when enabling extended bit-depth or
5017 * sampling rates, as not all qcom products support it.
5018 *
5019 * Suitable for calling only on initialization such as adev_open().
5020 * It fills the audio_device use_case_table[] array.
5021 *
5022 * Has a side-effect that it needs to configure audio routing / devices
5023 * in order to power up the devices and read the device parameters.
5024 * It does not acquire any hw device lock. Should restore the devices
5025 * back to "normal state" upon completion.
5026 */
5027static int adev_verify_devices(struct audio_device *adev)
5028{
5029 /* enumeration is a bit difficult because one really wants to pull
5030 * the use_case, device id, etc from the hidden pcm_device_table[].
5031 * In this case there are the following use cases and device ids.
5032 *
5033 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5034 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005035 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005036 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5037 * [USECASE_AUDIO_RECORD] = {0, 0},
5038 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5039 * [USECASE_VOICE_CALL] = {2, 2},
5040 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005041 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005042 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5043 */
5044
5045 /* should be the usecases enabled in adev_open_input_stream() */
5046 static const int test_in_usecases[] = {
5047 USECASE_AUDIO_RECORD,
5048 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5049 };
5050 /* should be the usecases enabled in adev_open_output_stream()*/
5051 static const int test_out_usecases[] = {
5052 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5053 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5054 };
5055 static const usecase_type_t usecase_type_by_dir[] = {
5056 PCM_PLAYBACK,
5057 PCM_CAPTURE,
5058 };
5059 static const unsigned flags_by_dir[] = {
5060 PCM_OUT,
5061 PCM_IN,
5062 };
5063
5064 size_t i;
5065 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005066 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005067 char info[512]; /* for possible debug info */
5068
5069 for (dir = 0; dir < 2; ++dir) {
5070 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5071 const unsigned flags_dir = flags_by_dir[dir];
5072 const size_t testsize =
5073 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5074 const int *testcases =
5075 dir ? test_in_usecases : test_out_usecases;
5076 const audio_devices_t audio_device =
5077 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5078
5079 for (i = 0; i < testsize; ++i) {
5080 const audio_usecase_t audio_usecase = testcases[i];
5081 int device_id;
5082 snd_device_t snd_device;
5083 struct pcm_params **pparams;
5084 struct stream_out out;
5085 struct stream_in in;
5086 struct audio_usecase uc_info;
5087 int retval;
5088
5089 pparams = &adev->use_case_table[audio_usecase];
5090 pcm_params_free(*pparams); /* can accept null input */
5091 *pparams = NULL;
5092
5093 /* find the device ID for the use case (signed, for error) */
5094 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5095 if (device_id < 0)
5096 continue;
5097
5098 /* prepare structures for device probing */
5099 memset(&uc_info, 0, sizeof(uc_info));
5100 uc_info.id = audio_usecase;
5101 uc_info.type = usecase_type;
5102 if (dir) {
5103 adev->active_input = &in;
5104 memset(&in, 0, sizeof(in));
5105 in.device = audio_device;
5106 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5107 uc_info.stream.in = &in;
5108 } else {
5109 adev->active_input = NULL;
5110 }
5111 memset(&out, 0, sizeof(out));
5112 out.devices = audio_device; /* only field needed in select_devices */
5113 uc_info.stream.out = &out;
5114 uc_info.devices = audio_device;
5115 uc_info.in_snd_device = SND_DEVICE_NONE;
5116 uc_info.out_snd_device = SND_DEVICE_NONE;
5117 list_add_tail(&adev->usecase_list, &uc_info.list);
5118
5119 /* select device - similar to start_(in/out)put_stream() */
5120 retval = select_devices(adev, audio_usecase);
5121 if (retval >= 0) {
5122 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5123#if LOG_NDEBUG == 0
5124 if (*pparams) {
5125 ALOGV("%s: (%s) card %d device %d", __func__,
5126 dir ? "input" : "output", card_id, device_id);
5127 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005128 } else {
5129 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5130 }
5131#endif
5132 }
5133
5134 /* deselect device - similar to stop_(in/out)put_stream() */
5135 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005136 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005137 /* 2. Disable the rx device */
5138 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005139 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005140 list_remove(&uc_info.list);
5141 }
5142 }
5143 adev->active_input = NULL; /* restore adev state */
5144 return 0;
5145}
5146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005147static int adev_close(hw_device_t *device)
5148{
Andy Hung31aca912014-03-20 17:14:59 -07005149 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005150 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005151
5152 if (!adev)
5153 return 0;
5154
5155 pthread_mutex_lock(&adev_init_lock);
5156
5157 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005158 audio_extn_snd_mon_unregister_listener(adev);
5159 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005160 audio_route_free(adev->audio_route);
5161 free(adev->snd_dev_ref_cnt);
5162 platform_deinit(adev->platform);
5163 audio_extn_extspk_deinit(adev->extspk);
5164 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005165 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005166 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5167 pcm_params_free(adev->use_case_table[i]);
5168 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005169 if (adev->adm_deinit)
5170 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005171 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005172 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005173 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005174
5175 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005177 return 0;
5178}
5179
Glenn Kasten4f993392014-05-14 07:30:48 -07005180/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5181 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5182 * just that it _might_ work.
5183 */
5184static int period_size_is_plausible_for_low_latency(int period_size)
5185{
5186 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005187 case 48:
5188 case 96:
5189 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005190 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005191 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005192 case 240:
5193 case 320:
5194 case 480:
5195 return 1;
5196 default:
5197 return 0;
5198 }
5199}
5200
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005201static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5202{
5203 int card;
5204 card_status_t status;
5205
5206 if (!parms)
5207 return;
5208
5209 if (parse_snd_card_status(parms, &card, &status) < 0)
5210 return;
5211
5212 pthread_mutex_lock(&adev->lock);
5213 bool valid_cb = (card == adev->snd_card);
5214 if (valid_cb) {
5215 if (adev->card_status != status) {
5216 adev->card_status = status;
5217 platform_snd_card_update(adev->platform, status);
5218 }
5219 }
5220 pthread_mutex_unlock(&adev->lock);
5221 return;
5222}
5223
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005224/* out and adev lock held */
5225static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5226{
5227 struct audio_usecase *uc_info;
5228 float left_p;
5229 float right_p;
5230 audio_devices_t devices;
5231
5232 uc_info = get_usecase_from_list(adev, out->usecase);
5233 if (uc_info == NULL) {
5234 ALOGE("%s: Could not find the usecase (%d) in the list",
5235 __func__, out->usecase);
5236 return -EINVAL;
5237 }
5238
5239 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5240 out->usecase, use_case_table[out->usecase]);
5241
5242 if (restore) {
5243 // restore A2DP device for active usecases and unmute if required
5244 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5245 !is_a2dp_device(uc_info->out_snd_device)) {
5246 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5247 select_devices(adev, uc_info->id);
5248 pthread_mutex_lock(&out->compr_mute_lock);
5249 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5250 (out->a2dp_compress_mute)) {
5251 out->a2dp_compress_mute = false;
5252 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5253 }
5254 pthread_mutex_unlock(&out->compr_mute_lock);
5255 }
5256 } else {
5257 // mute compress stream if suspended
5258 pthread_mutex_lock(&out->compr_mute_lock);
5259 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5260 (!out->a2dp_compress_mute)) {
5261 if (!out->standby) {
5262 ALOGD("%s: selecting speaker and muting stream", __func__);
5263 devices = out->devices;
5264 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5265 left_p = out->volume_l;
5266 right_p = out->volume_r;
5267 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5268 compress_pause(out->compr);
5269 set_compr_volume(&out->stream, 0.0f, 0.0f);
5270 out->a2dp_compress_mute = true;
5271 select_devices(adev, out->usecase);
5272 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5273 compress_resume(out->compr);
5274 out->devices = devices;
5275 out->volume_l = left_p;
5276 out->volume_r = right_p;
5277 }
5278 }
5279 pthread_mutex_unlock(&out->compr_mute_lock);
5280 }
5281 ALOGV("%s: exit", __func__);
5282 return 0;
5283}
5284
5285int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5286{
5287 int ret = 0;
5288
5289 lock_output_stream(out);
5290 pthread_mutex_lock(&adev->lock);
5291
5292 ret = check_a2dp_restore_l(adev, out, restore);
5293
5294 pthread_mutex_unlock(&adev->lock);
5295 pthread_mutex_unlock(&out->lock);
5296 return ret;
5297}
5298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005299static int adev_open(const hw_module_t *module, const char *name,
5300 hw_device_t **device)
5301{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005302 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005303
Eric Laurent2bafff12016-03-17 12:17:23 -07005304 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005305 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005306 pthread_mutex_lock(&adev_init_lock);
5307 if (audio_device_ref_count != 0) {
5308 *device = &adev->device.common;
5309 audio_device_ref_count++;
5310 ALOGV("%s: returning existing instance of adev", __func__);
5311 ALOGV("%s: exit", __func__);
5312 pthread_mutex_unlock(&adev_init_lock);
5313 return 0;
5314 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005315 adev = calloc(1, sizeof(struct audio_device));
5316
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005317 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5318
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005319 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5320 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5321 adev->device.common.module = (struct hw_module_t *)module;
5322 adev->device.common.close = adev_close;
5323
5324 adev->device.init_check = adev_init_check;
5325 adev->device.set_voice_volume = adev_set_voice_volume;
5326 adev->device.set_master_volume = adev_set_master_volume;
5327 adev->device.get_master_volume = adev_get_master_volume;
5328 adev->device.set_master_mute = adev_set_master_mute;
5329 adev->device.get_master_mute = adev_get_master_mute;
5330 adev->device.set_mode = adev_set_mode;
5331 adev->device.set_mic_mute = adev_set_mic_mute;
5332 adev->device.get_mic_mute = adev_get_mic_mute;
5333 adev->device.set_parameters = adev_set_parameters;
5334 adev->device.get_parameters = adev_get_parameters;
5335 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5336 adev->device.open_output_stream = adev_open_output_stream;
5337 adev->device.close_output_stream = adev_close_output_stream;
5338 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005339
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005340 adev->device.close_input_stream = adev_close_input_stream;
5341 adev->device.dump = adev_dump;
5342
5343 /* Set the default route before the PCM stream is opened */
5344 pthread_mutex_lock(&adev->lock);
5345 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005346 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005347 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005348 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005349 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005350 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005351 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005352 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005353 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005354 pthread_mutex_unlock(&adev->lock);
5355
5356 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005357 adev->platform = platform_init(adev);
5358 if (!adev->platform) {
5359 free(adev->snd_dev_ref_cnt);
5360 free(adev);
5361 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5362 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005363 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005364 return -EINVAL;
5365 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005366 adev->extspk = audio_extn_extspk_init(adev);
5367
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005368 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5369 if (adev->visualizer_lib == NULL) {
5370 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5371 } else {
5372 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5373 adev->visualizer_start_output =
5374 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5375 "visualizer_hal_start_output");
5376 adev->visualizer_stop_output =
5377 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5378 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005379 }
5380
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005381 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5382 if (adev->offload_effects_lib == NULL) {
5383 ALOGW("%s: DLOPEN failed for %s", __func__,
5384 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5385 } else {
5386 ALOGV("%s: DLOPEN successful for %s", __func__,
5387 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5388 adev->offload_effects_start_output =
5389 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5390 "offload_effects_bundle_hal_start_output");
5391 adev->offload_effects_stop_output =
5392 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5393 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005394 }
5395
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005396 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5397 if (adev->adm_lib == NULL) {
5398 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5399 } else {
5400 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5401 adev->adm_init = (adm_init_t)
5402 dlsym(adev->adm_lib, "adm_init");
5403 adev->adm_deinit = (adm_deinit_t)
5404 dlsym(adev->adm_lib, "adm_deinit");
5405 adev->adm_register_input_stream = (adm_register_input_stream_t)
5406 dlsym(adev->adm_lib, "adm_register_input_stream");
5407 adev->adm_register_output_stream = (adm_register_output_stream_t)
5408 dlsym(adev->adm_lib, "adm_register_output_stream");
5409 adev->adm_deregister_stream = (adm_deregister_stream_t)
5410 dlsym(adev->adm_lib, "adm_deregister_stream");
5411 adev->adm_request_focus = (adm_request_focus_t)
5412 dlsym(adev->adm_lib, "adm_request_focus");
5413 adev->adm_abandon_focus = (adm_abandon_focus_t)
5414 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005415 adev->adm_set_config = (adm_set_config_t)
5416 dlsym(adev->adm_lib, "adm_set_config");
5417 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5418 dlsym(adev->adm_lib, "adm_request_focus_v2");
5419 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5420 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5421 adev->adm_on_routing_change = (adm_on_routing_change_t)
5422 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005423 }
5424
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005425 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005426 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005427
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005428 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005429
Andy Hung31aca912014-03-20 17:14:59 -07005430 if (k_enable_extended_precision)
5431 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005432
Glenn Kasten4f993392014-05-14 07:30:48 -07005433 char value[PROPERTY_VALUE_MAX];
5434 int trial;
5435 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5436 trial = atoi(value);
5437 if (period_size_is_plausible_for_low_latency(trial)) {
5438 pcm_config_low_latency.period_size = trial;
5439 pcm_config_low_latency.start_threshold = trial / 4;
5440 pcm_config_low_latency.avail_min = trial / 4;
5441 configured_low_latency_capture_period_size = trial;
5442 }
5443 }
5444 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5445 trial = atoi(value);
5446 if (period_size_is_plausible_for_low_latency(trial)) {
5447 configured_low_latency_capture_period_size = trial;
5448 }
5449 }
5450
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005451 // commented as full set of app type cfg is sent from platform
5452 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005453 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005454
5455 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5456 af_period_multiplier = atoi(value);
5457 if (af_period_multiplier < 0) {
5458 af_period_multiplier = 2;
5459 } else if (af_period_multiplier > 4) {
5460 af_period_multiplier = 4;
5461 }
5462 ALOGV("new period_multiplier = %d", af_period_multiplier);
5463 }
5464
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005465 audio_extn_tfa_98xx_init(adev);
5466
vivek mehta1a9b7c02015-06-25 11:49:38 -07005467 pthread_mutex_unlock(&adev_init_lock);
5468
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005469 if (adev->adm_init)
5470 adev->adm_data = adev->adm_init();
5471
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005472 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005473 audio_extn_snd_mon_init();
5474 pthread_mutex_lock(&adev->lock);
5475 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5476 adev->card_status = CARD_STATUS_ONLINE;
5477 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005478 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005479
Eric Laurent2bafff12016-03-17 12:17:23 -07005480 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005481 return 0;
5482}
5483
5484static struct hw_module_methods_t hal_module_methods = {
5485 .open = adev_open,
5486};
5487
5488struct audio_module HAL_MODULE_INFO_SYM = {
5489 .common = {
5490 .tag = HARDWARE_MODULE_TAG,
5491 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5492 .hal_api_version = HARDWARE_HAL_API_VERSION,
5493 .id = AUDIO_HARDWARE_MODULE_ID,
5494 .name = "QCOM Audio HAL",
5495 .author = "Code Aurora Forum",
5496 .methods = &hal_module_methods,
5497 },
5498};