blob: 03437170e854f0d393ef7d7acb5904a144b9159c [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)) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003954 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003955 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003956 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003957 if (config->sample_rate == 0)
3958 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3959 if (config->channel_mask == 0)
3960 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3961 if (config->format == AUDIO_FORMAT_DEFAULT)
3962 config->format = AUDIO_FORMAT_PCM_16_BIT;
3963 } else if (is_usb_dev) {
3964 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3965 &config->format,
3966 &out->supported_formats[0],
3967 MAX_SUPPORTED_FORMATS,
3968 &config->channel_mask,
3969 &out->supported_channel_masks[0],
3970 MAX_SUPPORTED_CHANNEL_MASKS,
3971 &config->sample_rate,
3972 &out->supported_sample_rates[0],
3973 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003974 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003975 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003976 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003977 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003978 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003979
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003980
Haynes Mathew George569b7482017-05-08 14:44:27 -07003981 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003982 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003983 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003984 if (is_hdmi) {
3985 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3986 out->config = pcm_config_hdmi_multi;
3987 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3988 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3989 out->config = pcm_config_mmap_playback;
3990 out->stream.start = out_start;
3991 out->stream.stop = out_stop;
3992 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3993 out->stream.get_mmap_position = out_get_mmap_position;
3994 } else {
3995 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3996 out->config = pcm_config_hifi;
3997 }
3998
3999 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004000 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004001 if (is_hdmi) {
4002 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
4003 audio_bytes_per_sample(out->format));
4004 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004005 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004006 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07004007 pthread_mutex_lock(&adev->lock);
4008 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
4009 pthread_mutex_unlock(&adev->lock);
4010
4011 // reject offload during card offline to allow
4012 // fallback to s/w paths
4013 if (offline) {
4014 ret = -ENODEV;
4015 goto error_open;
4016 }
4017
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004018 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
4019 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
4020 ALOGE("%s: Unsupported Offload information", __func__);
4021 ret = -EINVAL;
4022 goto error_open;
4023 }
4024 if (!is_supported_format(config->offload_info.format)) {
4025 ALOGE("%s: Unsupported audio format", __func__);
4026 ret = -EINVAL;
4027 goto error_open;
4028 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004029 out->sample_rate = config->offload_info.sample_rate;
4030 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
4031 out->channel_mask = config->offload_info.channel_mask;
4032 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
4033 out->channel_mask = config->channel_mask;
4034 else
4035 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4036
4037 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004038
4039 out->compr_config.codec = (struct snd_codec *)
4040 calloc(1, sizeof(struct snd_codec));
4041
4042 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004043
4044 out->stream.set_callback = out_set_callback;
4045 out->stream.pause = out_pause;
4046 out->stream.resume = out_resume;
4047 out->stream.drain = out_drain;
4048 out->stream.flush = out_flush;
4049
4050 out->compr_config.codec->id =
4051 get_snd_codec_id(config->offload_info.format);
4052 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
4053 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004054 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004055 out->compr_config.codec->bit_rate =
4056 config->offload_info.bit_rate;
4057 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004058 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004059 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
4060
4061 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
4062 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004063
4064 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004065 create_offload_callback_thread(out);
4066 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
4067 __func__, config->offload_info.version,
4068 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02004069 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
4070 switch (config->sample_rate) {
4071 case 0:
4072 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4073 break;
4074 case 8000:
4075 case 16000:
4076 case 48000:
4077 out->sample_rate = config->sample_rate;
4078 break;
4079 default:
4080 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
4081 config->sample_rate);
4082 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4083 ret = -EINVAL;
4084 goto error_open;
4085 }
4086 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4087 switch (config->channel_mask) {
4088 case AUDIO_CHANNEL_NONE:
4089 case AUDIO_CHANNEL_OUT_STEREO:
4090 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4091 break;
4092 default:
4093 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
4094 config->channel_mask);
4095 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4096 ret = -EINVAL;
4097 goto error_open;
4098 }
4099 switch (config->format) {
4100 case AUDIO_FORMAT_DEFAULT:
4101 case AUDIO_FORMAT_PCM_16_BIT:
4102 out->format = AUDIO_FORMAT_PCM_16_BIT;
4103 break;
4104 default:
4105 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
4106 config->format);
4107 config->format = AUDIO_FORMAT_PCM_16_BIT;
4108 ret = -EINVAL;
4109 goto error_open;
4110 }
4111
4112 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004113 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004114 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004115 case 0:
4116 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
4117 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07004118 case 8000:
4119 case 16000:
4120 case 48000:
4121 out->sample_rate = config->sample_rate;
4122 break;
4123 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004124 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
4125 config->sample_rate);
4126 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4127 ret = -EINVAL;
4128 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004129 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004130 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
4131 switch (config->channel_mask) {
4132 case AUDIO_CHANNEL_NONE:
4133 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4134 break;
4135 case AUDIO_CHANNEL_OUT_STEREO:
4136 out->channel_mask = config->channel_mask;
4137 break;
4138 default:
4139 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
4140 config->channel_mask);
4141 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4142 ret = -EINVAL;
4143 break;
4144 }
4145 switch (config->format) {
4146 case AUDIO_FORMAT_DEFAULT:
4147 out->format = AUDIO_FORMAT_PCM_16_BIT;
4148 break;
4149 case AUDIO_FORMAT_PCM_16_BIT:
4150 out->format = config->format;
4151 break;
4152 default:
4153 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
4154 config->format);
4155 config->format = AUDIO_FORMAT_PCM_16_BIT;
4156 ret = -EINVAL;
4157 break;
4158 }
4159 if (ret != 0)
4160 goto error_open;
4161
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004162 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
4163 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004164 out->config.rate = out->sample_rate;
4165 out->config.channels =
4166 audio_channel_count_from_out_mask(out->channel_mask);
4167 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004168 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004169 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
4170 switch (config->sample_rate) {
4171 case 0:
4172 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4173 break;
4174 case 8000:
4175 case 16000:
4176 case 32000:
4177 case 48000:
4178 out->sample_rate = config->sample_rate;
4179 break;
4180 default:
4181 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
4182 config->sample_rate);
4183 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
4184 ret = -EINVAL;
4185 break;
4186 }
Eric Laurentad2dde92017-09-20 18:27:31 -07004187 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004188 switch (config->channel_mask) {
4189 case AUDIO_CHANNEL_NONE:
4190 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4191 break;
4192 case AUDIO_CHANNEL_OUT_STEREO:
4193 out->channel_mask = config->channel_mask;
4194 break;
4195 default:
4196 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
4197 config->channel_mask);
4198 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4199 ret = -EINVAL;
4200 break;
4201 }
4202 switch (config->format) {
4203 case AUDIO_FORMAT_DEFAULT:
4204 out->format = AUDIO_FORMAT_PCM_16_BIT;
4205 break;
4206 case AUDIO_FORMAT_PCM_16_BIT:
4207 out->format = config->format;
4208 break;
4209 default:
4210 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4211 config->format);
4212 config->format = AUDIO_FORMAT_PCM_16_BIT;
4213 ret = -EINVAL;
4214 break;
4215 }
4216 if (ret != 0)
4217 goto error_open;
4218
vivek mehtaa68fea62017-06-08 19:04:02 -07004219 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004220 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4221 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004222 out->config.rate = out->sample_rate;
4223 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004224 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004225 out->sample_rate,
4226 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004227 out->config.channels,
4228 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004229 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004230 out->config.period_size = buffer_size / frame_size;
4231 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4232 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004233 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004234 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004235 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4236 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004237 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004238 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4239 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004240 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004241 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004242 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004243 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004244 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004245 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4246 out->config = pcm_config_mmap_playback;
4247 out->stream.start = out_start;
4248 out->stream.stop = out_stop;
4249 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4250 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004251 } else {
4252 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4253 out->config = pcm_config_low_latency;
4254 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004255
4256 if (config->sample_rate == 0) {
4257 out->sample_rate = out->config.rate;
4258 } else {
4259 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004260 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004261 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4262 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4263 } else {
4264 out->channel_mask = config->channel_mask;
4265 }
4266 if (config->format == AUDIO_FORMAT_DEFAULT)
4267 out->format = audio_format_from_pcm_format(out->config.format);
4268 else if (!audio_is_linear_pcm(config->format)) {
4269 config->format = AUDIO_FORMAT_PCM_16_BIT;
4270 ret = -EINVAL;
4271 goto error_open;
4272 } else {
4273 out->format = config->format;
4274 }
4275
4276 out->config.rate = out->sample_rate;
4277 out->config.channels =
4278 audio_channel_count_from_out_mask(out->channel_mask);
4279 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4280 out->config.format = pcm_format_from_audio_format(out->format);
4281 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004282 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004283
4284 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4285 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004286 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004287 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4288 __func__, config->sample_rate, config->format, config->channel_mask);
4289 config->sample_rate = out->sample_rate;
4290 config->format = out->format;
4291 config->channel_mask = out->channel_mask;
4292 ret = -EINVAL;
4293 goto error_open;
4294 }
4295
Andy Hung6fcba9c2014-03-18 11:53:32 -07004296 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4297 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004298
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004299 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004300 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004301 adev->primary_output = out;
4302 else {
4303 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004304 ret = -EEXIST;
4305 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004306 }
4307 }
4308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004309 /* Check if this usecase is already existing */
4310 pthread_mutex_lock(&adev->lock);
4311 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4312 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004314 ret = -EEXIST;
4315 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 }
4317 pthread_mutex_unlock(&adev->lock);
4318
4319 out->stream.common.get_sample_rate = out_get_sample_rate;
4320 out->stream.common.set_sample_rate = out_set_sample_rate;
4321 out->stream.common.get_buffer_size = out_get_buffer_size;
4322 out->stream.common.get_channels = out_get_channels;
4323 out->stream.common.get_format = out_get_format;
4324 out->stream.common.set_format = out_set_format;
4325 out->stream.common.standby = out_standby;
4326 out->stream.common.dump = out_dump;
4327 out->stream.common.set_parameters = out_set_parameters;
4328 out->stream.common.get_parameters = out_get_parameters;
4329 out->stream.common.add_audio_effect = out_add_audio_effect;
4330 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4331 out->stream.get_latency = out_get_latency;
4332 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004333#ifdef NO_AUDIO_OUT
4334 out->stream.write = out_write_for_no_output;
4335#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004336 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004337#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004338 out->stream.get_render_position = out_get_render_position;
4339 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004340 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341
Eric Laurent0e46adf2016-12-16 12:49:24 -08004342 if (out->realtime)
4343 out->af_period_multiplier = af_period_multiplier;
4344 else
4345 out->af_period_multiplier = 1;
4346
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004347 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004348 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004349 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004351 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004352 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004353 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4354
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355 config->format = out->stream.common.get_format(&out->stream.common);
4356 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4357 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4358
Andy Hunga452b0a2017-03-15 14:51:15 -07004359 out->error_log = error_log_create(
4360 ERROR_LOG_ENTRIES,
4361 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4362
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004363 /*
4364 By locking output stream before registering, we allow the callback
4365 to update stream's state only after stream's initial state is set to
4366 adev state.
4367 */
4368 lock_output_stream(out);
4369 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4370 pthread_mutex_lock(&adev->lock);
4371 out->card_status = adev->card_status;
4372 pthread_mutex_unlock(&adev->lock);
4373 pthread_mutex_unlock(&out->lock);
4374
vivek mehta4a824772017-06-08 19:05:49 -07004375 stream_app_type_cfg_init(&out->app_type_cfg);
4376
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004377 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004378
Eric Laurent994a6932013-07-17 11:51:42 -07004379 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004381
4382error_open:
4383 free(out);
4384 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004385 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004386 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387}
4388
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004389static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 struct audio_stream_out *stream)
4391{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004392 struct stream_out *out = (struct stream_out *)stream;
4393 struct audio_device *adev = out->dev;
4394
Eric Laurent994a6932013-07-17 11:51:42 -07004395 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004396
4397 // must deregister from sndmonitor first to prevent races
4398 // between the callback and close_stream
4399 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004400 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004401 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4402 destroy_offload_callback_thread(out);
4403
4404 if (out->compr_config.codec != NULL)
4405 free(out->compr_config.codec);
4406 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004407
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004408 out->a2dp_compress_mute = false;
4409
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004410 if (adev->voice_tx_output == out)
4411 adev->voice_tx_output = NULL;
4412
Andy Hunga452b0a2017-03-15 14:51:15 -07004413 error_log_destroy(out->error_log);
4414 out->error_log = NULL;
4415
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004416 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004417 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004418 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004419 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004420 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421}
4422
4423static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4424{
4425 struct audio_device *adev = (struct audio_device *)dev;
4426 struct str_parms *parms;
4427 char *str;
4428 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004429 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004430 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004431 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432
Joe Onorato188b6222016-03-01 11:02:27 -08004433 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004434
4435 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004436
4437 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004438 status = voice_set_parameters(adev, parms);
4439 if (status != 0) {
4440 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441 }
4442
4443 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4444 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004445 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004446 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4447 adev->bluetooth_nrec = true;
4448 else
4449 adev->bluetooth_nrec = false;
4450 }
4451
4452 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4453 if (ret >= 0) {
4454 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4455 adev->screen_off = false;
4456 else
4457 adev->screen_off = true;
4458 }
4459
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004460 ret = str_parms_get_int(parms, "rotation", &val);
4461 if (ret >= 0) {
4462 bool reverse_speakers = false;
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004463 switch (val) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004464 // FIXME: note that the code below assumes that the speakers are in the correct placement
4465 // relative to the user when the device is rotated 90deg from its default rotation. This
4466 // assumption is device-specific, not platform-specific like this code.
4467 case 270:
4468 reverse_speakers = true;
4469 break;
4470 case 0:
4471 case 90:
4472 case 180:
4473 break;
4474 default:
4475 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004476 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004477 }
Eric Laurent03f09432014-03-25 18:09:11 -07004478 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004479 // check and set swap
4480 // - check if orientation changed and speaker active
4481 // - set rotation and cache the rotation value
4482 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004483 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004484 }
4485
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004486 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4487 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004488 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004489 }
4490
David Linee3fe402017-03-13 10:00:42 -07004491 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4492 if (ret >= 0) {
4493 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004494 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004495 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4496 if (ret >= 0) {
4497 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004498 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004499 }
Eric Laurent99dab492017-06-17 15:19:08 -07004500 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004501 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4502 if (ret >= 0) {
4503 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004504 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004505 }
4506 }
4507 }
4508
4509 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4510 if (ret >= 0) {
4511 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004512 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004513 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4514 if (ret >= 0) {
4515 const int card = atoi(value);
4516
Eric Laurent99dab492017-06-17 15:19:08 -07004517 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004518 }
Eric Laurent99dab492017-06-17 15:19:08 -07004519 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004520 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4521 if (ret >= 0) {
4522 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004523 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004524 }
4525 }
4526 }
4527
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004528 audio_extn_hfp_set_parameters(adev, parms);
Aniket Kumar Lata26483012018-01-31 20:21:42 -08004529 audio_extn_a2dp_set_parameters(parms);
4530 // reconfigure should be done only after updating A2DP state in audio extension
4531 ret = str_parms_get_str(parms,"reconfigA2dp", value, sizeof(value));
4532 if (ret >= 0) {
4533 struct audio_usecase *usecase;
4534 struct listnode *node;
4535 list_for_each(node, &adev->usecase_list) {
4536 usecase = node_to_item(node, struct audio_usecase, list);
4537 if ((usecase->type == PCM_PLAYBACK) &&
4538 (usecase->devices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP)) {
4539 ALOGD("%s: reconfigure A2DP... forcing device switch", __func__);
4540
4541 pthread_mutex_unlock(&adev->lock);
4542 lock_output_stream(usecase->stream.out);
4543 pthread_mutex_lock(&adev->lock);
4544 audio_extn_a2dp_set_handoff_mode(true);
4545 // force device switch to reconfigure encoder
4546 select_devices(adev, usecase->id);
4547 audio_extn_a2dp_set_handoff_mode(false);
4548 pthread_mutex_unlock(&usecase->stream.out->lock);
4549 break;
4550 }
4551 }
4552 }
4553
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004554done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004556 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004557 ALOGV("%s: exit with code(%d)", __func__, status);
4558 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004559}
4560
4561static char* adev_get_parameters(const struct audio_hw_device *dev,
4562 const char *keys)
4563{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004564 struct audio_device *adev = (struct audio_device *)dev;
4565 struct str_parms *reply = str_parms_create();
4566 struct str_parms *query = str_parms_create_str(keys);
4567 char *str;
4568
4569 pthread_mutex_lock(&adev->lock);
4570
4571 voice_get_parameters(adev, query, reply);
4572 str = str_parms_to_str(reply);
4573 str_parms_destroy(query);
4574 str_parms_destroy(reply);
4575
4576 pthread_mutex_unlock(&adev->lock);
4577 ALOGV("%s: exit: returns - %s", __func__, str);
4578 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004579}
4580
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004581static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004582{
4583 return 0;
4584}
4585
Haynes Mathew George5191a852013-09-11 14:19:36 -07004586static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4587{
4588 int ret;
4589 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004590
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004591 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4592
Haynes Mathew George5191a852013-09-11 14:19:36 -07004593 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004594 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004595 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004596
Haynes Mathew George5191a852013-09-11 14:19:36 -07004597 return ret;
4598}
4599
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004600static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601{
4602 return -ENOSYS;
4603}
4604
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004605static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4606 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004607{
4608 return -ENOSYS;
4609}
4610
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004611static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004612{
4613 return -ENOSYS;
4614}
4615
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004616static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004617{
4618 return -ENOSYS;
4619}
4620
4621static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4622{
4623 struct audio_device *adev = (struct audio_device *)dev;
4624
4625 pthread_mutex_lock(&adev->lock);
4626 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004627 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004628 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004629 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4630 voice_is_in_call(adev)) {
4631 voice_stop_call(adev);
4632 adev->current_call_output = NULL;
4633 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634 }
4635 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004636
4637 audio_extn_extspk_set_mode(adev->extspk, mode);
4638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004639 return 0;
4640}
4641
4642static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4643{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004644 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646
Eric Laurent2bafff12016-03-17 12:17:23 -07004647 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004648 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004649 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4650 ret = audio_extn_hfp_set_mic_mute(adev, state);
4651 } else {
4652 ret = voice_set_mic_mute(adev, state);
4653 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004654 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004655 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004656
4657 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004658}
4659
4660static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4661{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004662 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004663 return 0;
4664}
4665
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004666static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004667 const struct audio_config *config)
4668{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004669 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004670
Eric Laurent74b55762017-07-09 17:04:53 -07004671 /* Don't know if USB HIFI in this context so use true to be conservative */
4672 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4673 true /*is_usb_hifi */) != 0)
4674 return 0;
4675
vivek mehtaa68fea62017-06-08 19:04:02 -07004676 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4677 config->sample_rate, config->format,
4678 channel_count,
4679 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004680}
4681
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004682static bool adev_input_allow_hifi_record(struct audio_device *adev,
4683 audio_devices_t devices,
4684 audio_input_flags_t flags,
4685 audio_source_t source) {
4686 const bool allowed = true;
4687
4688 if (!audio_is_usb_in_device(devices))
4689 return !allowed;
4690
4691 switch (flags) {
4692 case AUDIO_INPUT_FLAG_NONE:
4693 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4694 break;
4695 default:
4696 return !allowed;
4697 }
4698
4699 switch (source) {
4700 case AUDIO_SOURCE_DEFAULT:
4701 case AUDIO_SOURCE_MIC:
4702 case AUDIO_SOURCE_UNPROCESSED:
4703 break;
4704 default:
4705 return !allowed;
4706 }
4707
4708 switch (adev->mode) {
4709 case 0:
4710 break;
4711 default:
4712 return !allowed;
4713 }
4714
4715 return allowed;
4716}
4717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004718static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004719 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004720 audio_devices_t devices,
4721 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004722 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004723 audio_input_flags_t flags,
4724 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004725 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004726{
4727 struct audio_device *adev = (struct audio_device *)dev;
4728 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004729 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004730 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004731 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004732 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004733 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4734 devices,
4735 flags,
4736 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004737 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004738 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004739
Andy Hungd9653bd2017-08-01 19:31:39 -07004740 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4741 return -ENOSYS;
4742 }
4743
Eric Laurent74b55762017-07-09 17:04:53 -07004744 if (!(is_usb_dev && may_use_hifi_record)) {
4745 if (config->sample_rate == 0)
4746 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4747 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4748 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4749 if (config->format == AUDIO_FORMAT_DEFAULT)
4750 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004751
Eric Laurent74b55762017-07-09 17:04:53 -07004752 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4753
4754 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4755 return -EINVAL;
4756 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004758 if (audio_extn_tfa_98xx_is_supported() &&
4759 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004760 return -EINVAL;
4761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004762 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4763
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004764 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004765 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767 in->stream.common.get_sample_rate = in_get_sample_rate;
4768 in->stream.common.set_sample_rate = in_set_sample_rate;
4769 in->stream.common.get_buffer_size = in_get_buffer_size;
4770 in->stream.common.get_channels = in_get_channels;
4771 in->stream.common.get_format = in_get_format;
4772 in->stream.common.set_format = in_set_format;
4773 in->stream.common.standby = in_standby;
4774 in->stream.common.dump = in_dump;
4775 in->stream.common.set_parameters = in_set_parameters;
4776 in->stream.common.get_parameters = in_get_parameters;
4777 in->stream.common.add_audio_effect = in_add_audio_effect;
4778 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4779 in->stream.set_gain = in_set_gain;
4780 in->stream.read = in_read;
4781 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004782 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004783
4784 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004785 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004786 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004787 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004788 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004789 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790
Haynes Mathew George569b7482017-05-08 14:44:27 -07004791 if (is_usb_dev && may_use_hifi_record) {
4792 /* HiFi record selects an appropriate format, channel, rate combo
4793 depending on sink capabilities*/
4794 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4795 &config->format,
4796 &in->supported_formats[0],
4797 MAX_SUPPORTED_FORMATS,
4798 &config->channel_mask,
4799 &in->supported_channel_masks[0],
4800 MAX_SUPPORTED_CHANNEL_MASKS,
4801 &config->sample_rate,
4802 &in->supported_sample_rates[0],
4803 MAX_SUPPORTED_SAMPLE_RATES);
4804 if (ret != 0) {
4805 ret = -EINVAL;
4806 goto err_open;
4807 }
Eric Laurent74b55762017-07-09 17:04:53 -07004808 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004809 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004810 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004811 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4812 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4813 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4814 bool ret_error = false;
4815 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4816 from HAL is 8_24
4817 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4818 8_24 return error indicating supported format is 8_24
4819 *> In case of any other source requesting 24 bit or float return error
4820 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004821
vivek mehta57ff9b52016-04-28 14:13:08 -07004822 on error flinger will retry with supported format passed
4823 */
4824 if (source != AUDIO_SOURCE_UNPROCESSED) {
4825 config->format = AUDIO_FORMAT_PCM_16_BIT;
4826 ret_error = true;
4827 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4828 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4829 ret_error = true;
4830 }
4831
4832 if (ret_error) {
4833 ret = -EINVAL;
4834 goto err_open;
4835 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004836 }
4837
vivek mehta57ff9b52016-04-28 14:13:08 -07004838 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004839 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004840
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004842 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4843 if (config->sample_rate == 0)
4844 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4845 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4846 config->sample_rate != 8000) {
4847 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4848 ret = -EINVAL;
4849 goto err_open;
4850 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004851
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004852 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4853 config->format = AUDIO_FORMAT_PCM_16_BIT;
4854 ret = -EINVAL;
4855 goto err_open;
4856 }
4857
4858 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4859 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004860 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004861 } else if (is_usb_dev && may_use_hifi_record) {
4862 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4863 in->config = pcm_config_audio_capture;
4864 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004865 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4866 config->sample_rate,
4867 config->format,
4868 channel_count,
4869 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004870 in->config.period_size = buffer_size / frame_size;
4871 in->config.rate = config->sample_rate;
4872 in->af_period_multiplier = 1;
4873 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004874 } else {
4875 in->usecase = USECASE_AUDIO_RECORD;
4876 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004877 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004878 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004879#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004880 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004881#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004882 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004883 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004884 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004885 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004886 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4887 config->sample_rate,
4888 config->format,
4889 channel_count,
4890 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004891 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004892 in->config.rate = config->sample_rate;
4893 in->af_period_multiplier = 1;
4894 } else {
4895 // period size is left untouched for rt mode playback
4896 in->config = pcm_config_audio_capture_rt;
4897 in->af_period_multiplier = af_period_multiplier;
4898 }
4899 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4900 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004901 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004902 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4903 in->config = pcm_config_mmap_capture;
4904 in->stream.start = in_start;
4905 in->stream.stop = in_stop;
4906 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4907 in->stream.get_mmap_position = in_get_mmap_position;
4908 in->af_period_multiplier = 1;
4909 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004910 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004911 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004912 (config->sample_rate == 8000 ||
4913 config->sample_rate == 16000 ||
4914 config->sample_rate == 32000 ||
4915 config->sample_rate == 48000) &&
4916 channel_count == 1) {
4917 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4918 in->config = pcm_config_audio_capture;
4919 frame_size = audio_stream_in_frame_size(&in->stream);
4920 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4921 config->sample_rate,
4922 config->format,
4923 channel_count, false /*is_low_latency*/);
4924 in->config.period_size = buffer_size / frame_size;
4925 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4926 in->config.rate = config->sample_rate;
4927 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004928 } else {
4929 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004930 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004931 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4932 config->sample_rate,
4933 config->format,
4934 channel_count,
4935 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004936 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004937 in->config.rate = config->sample_rate;
4938 in->af_period_multiplier = 1;
4939 }
4940 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4941 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004942 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004944 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004945 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004946
Andy Hungd13f0d32017-06-12 13:58:37 -07004947 in->error_log = error_log_create(
4948 ERROR_LOG_ENTRIES,
4949 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4950
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004951 /* This stream could be for sound trigger lab,
4952 get sound trigger pcm if present */
4953 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004954
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004955 lock_input_stream(in);
4956 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4957 pthread_mutex_lock(&adev->lock);
4958 in->card_status = adev->card_status;
4959 pthread_mutex_unlock(&adev->lock);
4960 pthread_mutex_unlock(&in->lock);
4961
vivek mehta4a824772017-06-08 19:05:49 -07004962 stream_app_type_cfg_init(&in->app_type_cfg);
4963
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004964 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004965 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004966 return 0;
4967
4968err_open:
4969 free(in);
4970 *stream_in = NULL;
4971 return ret;
4972}
4973
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004974static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004975 struct audio_stream_in *stream)
4976{
Andy Hungd13f0d32017-06-12 13:58:37 -07004977 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004978 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004979
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004980 // must deregister from sndmonitor first to prevent races
4981 // between the callback and close_stream
4982 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004983 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004984
4985 error_log_destroy(in->error_log);
4986 in->error_log = NULL;
4987
Andy Hung0dbb52b2017-08-09 13:51:38 -07004988 pthread_mutex_destroy(&in->pre_lock);
4989 pthread_mutex_destroy(&in->lock);
4990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004991 free(stream);
4992
4993 return;
4994}
4995
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004996static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004997{
4998 return 0;
4999}
5000
Andy Hung31aca912014-03-20 17:14:59 -07005001/* verifies input and output devices and their capabilities.
5002 *
5003 * This verification is required when enabling extended bit-depth or
5004 * sampling rates, as not all qcom products support it.
5005 *
5006 * Suitable for calling only on initialization such as adev_open().
5007 * It fills the audio_device use_case_table[] array.
5008 *
5009 * Has a side-effect that it needs to configure audio routing / devices
5010 * in order to power up the devices and read the device parameters.
5011 * It does not acquire any hw device lock. Should restore the devices
5012 * back to "normal state" upon completion.
5013 */
5014static int adev_verify_devices(struct audio_device *adev)
5015{
5016 /* enumeration is a bit difficult because one really wants to pull
5017 * the use_case, device id, etc from the hidden pcm_device_table[].
5018 * In this case there are the following use cases and device ids.
5019 *
5020 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
5021 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005022 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07005023 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
5024 * [USECASE_AUDIO_RECORD] = {0, 0},
5025 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
5026 * [USECASE_VOICE_CALL] = {2, 2},
5027 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005028 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07005029 * USECASE_VOICE_CALL omitted, but possible for either input or output.
5030 */
5031
5032 /* should be the usecases enabled in adev_open_input_stream() */
5033 static const int test_in_usecases[] = {
5034 USECASE_AUDIO_RECORD,
5035 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
5036 };
5037 /* should be the usecases enabled in adev_open_output_stream()*/
5038 static const int test_out_usecases[] = {
5039 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
5040 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
5041 };
5042 static const usecase_type_t usecase_type_by_dir[] = {
5043 PCM_PLAYBACK,
5044 PCM_CAPTURE,
5045 };
5046 static const unsigned flags_by_dir[] = {
5047 PCM_OUT,
5048 PCM_IN,
5049 };
5050
5051 size_t i;
5052 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005053 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07005054 char info[512]; /* for possible debug info */
5055
5056 for (dir = 0; dir < 2; ++dir) {
5057 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
5058 const unsigned flags_dir = flags_by_dir[dir];
5059 const size_t testsize =
5060 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
5061 const int *testcases =
5062 dir ? test_in_usecases : test_out_usecases;
5063 const audio_devices_t audio_device =
5064 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
5065
5066 for (i = 0; i < testsize; ++i) {
5067 const audio_usecase_t audio_usecase = testcases[i];
5068 int device_id;
5069 snd_device_t snd_device;
5070 struct pcm_params **pparams;
5071 struct stream_out out;
5072 struct stream_in in;
5073 struct audio_usecase uc_info;
5074 int retval;
5075
5076 pparams = &adev->use_case_table[audio_usecase];
5077 pcm_params_free(*pparams); /* can accept null input */
5078 *pparams = NULL;
5079
5080 /* find the device ID for the use case (signed, for error) */
5081 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
5082 if (device_id < 0)
5083 continue;
5084
5085 /* prepare structures for device probing */
5086 memset(&uc_info, 0, sizeof(uc_info));
5087 uc_info.id = audio_usecase;
5088 uc_info.type = usecase_type;
5089 if (dir) {
5090 adev->active_input = &in;
5091 memset(&in, 0, sizeof(in));
5092 in.device = audio_device;
5093 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
5094 uc_info.stream.in = &in;
5095 } else {
5096 adev->active_input = NULL;
5097 }
5098 memset(&out, 0, sizeof(out));
5099 out.devices = audio_device; /* only field needed in select_devices */
5100 uc_info.stream.out = &out;
5101 uc_info.devices = audio_device;
5102 uc_info.in_snd_device = SND_DEVICE_NONE;
5103 uc_info.out_snd_device = SND_DEVICE_NONE;
5104 list_add_tail(&adev->usecase_list, &uc_info.list);
5105
5106 /* select device - similar to start_(in/out)put_stream() */
5107 retval = select_devices(adev, audio_usecase);
5108 if (retval >= 0) {
5109 *pparams = pcm_params_get(card_id, device_id, flags_dir);
5110#if LOG_NDEBUG == 0
5111 if (*pparams) {
5112 ALOGV("%s: (%s) card %d device %d", __func__,
5113 dir ? "input" : "output", card_id, device_id);
5114 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07005115 } else {
5116 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
5117 }
5118#endif
5119 }
5120
5121 /* deselect device - similar to stop_(in/out)put_stream() */
5122 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07005123 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07005124 /* 2. Disable the rx device */
5125 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07005126 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07005127 list_remove(&uc_info.list);
5128 }
5129 }
5130 adev->active_input = NULL; /* restore adev state */
5131 return 0;
5132}
5133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005134static int adev_close(hw_device_t *device)
5135{
Andy Hung31aca912014-03-20 17:14:59 -07005136 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005137 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005138
5139 if (!adev)
5140 return 0;
5141
5142 pthread_mutex_lock(&adev_init_lock);
5143
5144 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005145 audio_extn_snd_mon_unregister_listener(adev);
5146 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005147 audio_route_free(adev->audio_route);
5148 free(adev->snd_dev_ref_cnt);
5149 platform_deinit(adev->platform);
5150 audio_extn_extspk_deinit(adev->extspk);
5151 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005152 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07005153 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
5154 pcm_params_free(adev->use_case_table[i]);
5155 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005156 if (adev->adm_deinit)
5157 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07005158 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005159 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07005160 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07005161
5162 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005164 return 0;
5165}
5166
Glenn Kasten4f993392014-05-14 07:30:48 -07005167/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
5168 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
5169 * just that it _might_ work.
5170 */
5171static int period_size_is_plausible_for_low_latency(int period_size)
5172{
5173 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005174 case 48:
5175 case 96:
5176 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07005177 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07005178 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07005179 case 240:
5180 case 320:
5181 case 480:
5182 return 1;
5183 default:
5184 return 0;
5185 }
5186}
5187
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005188static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
5189{
5190 int card;
5191 card_status_t status;
5192
5193 if (!parms)
5194 return;
5195
5196 if (parse_snd_card_status(parms, &card, &status) < 0)
5197 return;
5198
5199 pthread_mutex_lock(&adev->lock);
5200 bool valid_cb = (card == adev->snd_card);
5201 if (valid_cb) {
5202 if (adev->card_status != status) {
5203 adev->card_status = status;
5204 platform_snd_card_update(adev->platform, status);
5205 }
5206 }
5207 pthread_mutex_unlock(&adev->lock);
5208 return;
5209}
5210
Aniket Kumar Lata26483012018-01-31 20:21:42 -08005211/* out and adev lock held */
5212static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
5213{
5214 struct audio_usecase *uc_info;
5215 float left_p;
5216 float right_p;
5217 audio_devices_t devices;
5218
5219 uc_info = get_usecase_from_list(adev, out->usecase);
5220 if (uc_info == NULL) {
5221 ALOGE("%s: Could not find the usecase (%d) in the list",
5222 __func__, out->usecase);
5223 return -EINVAL;
5224 }
5225
5226 ALOGD("%s: enter: usecase(%d: %s)", __func__,
5227 out->usecase, use_case_table[out->usecase]);
5228
5229 if (restore) {
5230 // restore A2DP device for active usecases and unmute if required
5231 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
5232 !is_a2dp_device(uc_info->out_snd_device)) {
5233 ALOGD("%s: restoring A2DP and unmuting stream", __func__);
5234 select_devices(adev, uc_info->id);
5235 pthread_mutex_lock(&out->compr_mute_lock);
5236 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5237 (out->a2dp_compress_mute)) {
5238 out->a2dp_compress_mute = false;
5239 set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5240 }
5241 pthread_mutex_unlock(&out->compr_mute_lock);
5242 }
5243 } else {
5244 // mute compress stream if suspended
5245 pthread_mutex_lock(&out->compr_mute_lock);
5246 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
5247 (!out->a2dp_compress_mute)) {
5248 if (!out->standby) {
5249 ALOGD("%s: selecting speaker and muting stream", __func__);
5250 devices = out->devices;
5251 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
5252 left_p = out->volume_l;
5253 right_p = out->volume_r;
5254 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5255 compress_pause(out->compr);
5256 set_compr_volume(&out->stream, 0.0f, 0.0f);
5257 out->a2dp_compress_mute = true;
5258 select_devices(adev, out->usecase);
5259 if (out->offload_state == OFFLOAD_STATE_PLAYING)
5260 compress_resume(out->compr);
5261 out->devices = devices;
5262 out->volume_l = left_p;
5263 out->volume_r = right_p;
5264 }
5265 }
5266 pthread_mutex_unlock(&out->compr_mute_lock);
5267 }
5268 ALOGV("%s: exit", __func__);
5269 return 0;
5270}
5271
5272int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
5273{
5274 int ret = 0;
5275
5276 lock_output_stream(out);
5277 pthread_mutex_lock(&adev->lock);
5278
5279 ret = check_a2dp_restore_l(adev, out, restore);
5280
5281 pthread_mutex_unlock(&adev->lock);
5282 pthread_mutex_unlock(&out->lock);
5283 return ret;
5284}
5285
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005286static int adev_open(const hw_module_t *module, const char *name,
5287 hw_device_t **device)
5288{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07005289 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005290
Eric Laurent2bafff12016-03-17 12:17:23 -07005291 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005292 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005293 pthread_mutex_lock(&adev_init_lock);
5294 if (audio_device_ref_count != 0) {
5295 *device = &adev->device.common;
5296 audio_device_ref_count++;
5297 ALOGV("%s: returning existing instance of adev", __func__);
5298 ALOGV("%s: exit", __func__);
5299 pthread_mutex_unlock(&adev_init_lock);
5300 return 0;
5301 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005302 adev = calloc(1, sizeof(struct audio_device));
5303
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005304 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005306 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5307 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5308 adev->device.common.module = (struct hw_module_t *)module;
5309 adev->device.common.close = adev_close;
5310
5311 adev->device.init_check = adev_init_check;
5312 adev->device.set_voice_volume = adev_set_voice_volume;
5313 adev->device.set_master_volume = adev_set_master_volume;
5314 adev->device.get_master_volume = adev_get_master_volume;
5315 adev->device.set_master_mute = adev_set_master_mute;
5316 adev->device.get_master_mute = adev_get_master_mute;
5317 adev->device.set_mode = adev_set_mode;
5318 adev->device.set_mic_mute = adev_set_mic_mute;
5319 adev->device.get_mic_mute = adev_get_mic_mute;
5320 adev->device.set_parameters = adev_set_parameters;
5321 adev->device.get_parameters = adev_get_parameters;
5322 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5323 adev->device.open_output_stream = adev_open_output_stream;
5324 adev->device.close_output_stream = adev_close_output_stream;
5325 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005327 adev->device.close_input_stream = adev_close_input_stream;
5328 adev->device.dump = adev_dump;
5329
5330 /* Set the default route before the PCM stream is opened */
5331 pthread_mutex_lock(&adev->lock);
5332 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005333 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005334 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005335 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005336 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005337 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005338 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005339 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005340 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005341 pthread_mutex_unlock(&adev->lock);
5342
5343 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005344 adev->platform = platform_init(adev);
5345 if (!adev->platform) {
5346 free(adev->snd_dev_ref_cnt);
5347 free(adev);
5348 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5349 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005350 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005351 return -EINVAL;
5352 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005353 adev->extspk = audio_extn_extspk_init(adev);
5354
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005355 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5356 if (adev->visualizer_lib == NULL) {
5357 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5358 } else {
5359 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5360 adev->visualizer_start_output =
5361 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5362 "visualizer_hal_start_output");
5363 adev->visualizer_stop_output =
5364 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5365 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005366 }
5367
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005368 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5369 if (adev->offload_effects_lib == NULL) {
5370 ALOGW("%s: DLOPEN failed for %s", __func__,
5371 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5372 } else {
5373 ALOGV("%s: DLOPEN successful for %s", __func__,
5374 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5375 adev->offload_effects_start_output =
5376 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5377 "offload_effects_bundle_hal_start_output");
5378 adev->offload_effects_stop_output =
5379 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5380 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005381 }
5382
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005383 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5384 if (adev->adm_lib == NULL) {
5385 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5386 } else {
5387 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5388 adev->adm_init = (adm_init_t)
5389 dlsym(adev->adm_lib, "adm_init");
5390 adev->adm_deinit = (adm_deinit_t)
5391 dlsym(adev->adm_lib, "adm_deinit");
5392 adev->adm_register_input_stream = (adm_register_input_stream_t)
5393 dlsym(adev->adm_lib, "adm_register_input_stream");
5394 adev->adm_register_output_stream = (adm_register_output_stream_t)
5395 dlsym(adev->adm_lib, "adm_register_output_stream");
5396 adev->adm_deregister_stream = (adm_deregister_stream_t)
5397 dlsym(adev->adm_lib, "adm_deregister_stream");
5398 adev->adm_request_focus = (adm_request_focus_t)
5399 dlsym(adev->adm_lib, "adm_request_focus");
5400 adev->adm_abandon_focus = (adm_abandon_focus_t)
5401 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005402 adev->adm_set_config = (adm_set_config_t)
5403 dlsym(adev->adm_lib, "adm_set_config");
5404 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5405 dlsym(adev->adm_lib, "adm_request_focus_v2");
5406 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5407 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5408 adev->adm_on_routing_change = (adm_on_routing_change_t)
5409 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005410 }
5411
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005412 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005413 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005415 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005416
Andy Hung31aca912014-03-20 17:14:59 -07005417 if (k_enable_extended_precision)
5418 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005419
Glenn Kasten4f993392014-05-14 07:30:48 -07005420 char value[PROPERTY_VALUE_MAX];
5421 int trial;
5422 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5423 trial = atoi(value);
5424 if (period_size_is_plausible_for_low_latency(trial)) {
5425 pcm_config_low_latency.period_size = trial;
5426 pcm_config_low_latency.start_threshold = trial / 4;
5427 pcm_config_low_latency.avail_min = trial / 4;
5428 configured_low_latency_capture_period_size = trial;
5429 }
5430 }
5431 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5432 trial = atoi(value);
5433 if (period_size_is_plausible_for_low_latency(trial)) {
5434 configured_low_latency_capture_period_size = trial;
5435 }
5436 }
5437
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005438 // commented as full set of app type cfg is sent from platform
5439 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005440 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005441
5442 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5443 af_period_multiplier = atoi(value);
5444 if (af_period_multiplier < 0) {
5445 af_period_multiplier = 2;
5446 } else if (af_period_multiplier > 4) {
5447 af_period_multiplier = 4;
5448 }
5449 ALOGV("new period_multiplier = %d", af_period_multiplier);
5450 }
5451
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005452 audio_extn_tfa_98xx_init(adev);
5453
vivek mehta1a9b7c02015-06-25 11:49:38 -07005454 pthread_mutex_unlock(&adev_init_lock);
5455
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005456 if (adev->adm_init)
5457 adev->adm_data = adev->adm_init();
5458
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005459 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005460 audio_extn_snd_mon_init();
5461 pthread_mutex_lock(&adev->lock);
5462 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5463 adev->card_status = CARD_STATUS_ONLINE;
5464 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005465 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005466
Eric Laurent2bafff12016-03-17 12:17:23 -07005467 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005468 return 0;
5469}
5470
5471static struct hw_module_methods_t hal_module_methods = {
5472 .open = adev_open,
5473};
5474
5475struct audio_module HAL_MODULE_INFO_SYM = {
5476 .common = {
5477 .tag = HARDWARE_MODULE_TAG,
5478 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5479 .hal_api_version = HARDWARE_HAL_API_VERSION,
5480 .id = AUDIO_HARDWARE_MODULE_ID,
5481 .name = "QCOM Audio HAL",
5482 .author = "Code Aurora Forum",
5483 .methods = &hal_module_methods,
5484 },
5485};