blob: f2dec25afa91e5de01528e908097730a5886a96c [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
Haynes Mathew George03c40102016-01-29 17:57:48 -0800324static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
325 int flags __unused)
326{
327 int dir = 0;
328 switch (uc_id) {
329 case USECASE_AUDIO_RECORD_LOW_LATENCY:
330 dir = 1;
331 case USECASE_AUDIO_PLAYBACK_ULL:
332 break;
333 default:
334 return false;
335 }
336
337 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
338 PCM_PLAYBACK : PCM_CAPTURE);
339 if (adev->adm_is_noirq_avail)
340 return adev->adm_is_noirq_avail(adev->adm_data,
341 adev->snd_card, dev_id, dir);
342 return false;
343}
344
345static void register_out_stream(struct stream_out *out)
346{
347 struct audio_device *adev = out->dev;
348 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
349 return;
350
351 if (!adev->adm_register_output_stream)
352 return;
353
354 adev->adm_register_output_stream(adev->adm_data,
355 out->handle,
356 out->flags);
357
358 if (!adev->adm_set_config)
359 return;
360
361 if (out->realtime) {
362 adev->adm_set_config(adev->adm_data,
363 out->handle,
364 out->pcm, &out->config);
365 }
366}
367
368static void register_in_stream(struct stream_in *in)
369{
370 struct audio_device *adev = in->dev;
371 if (!adev->adm_register_input_stream)
372 return;
373
374 adev->adm_register_input_stream(adev->adm_data,
375 in->capture_handle,
376 in->flags);
377
378 if (!adev->adm_set_config)
379 return;
380
381 if (in->realtime) {
382 adev->adm_set_config(adev->adm_data,
383 in->capture_handle,
384 in->pcm,
385 &in->config);
386 }
387}
388
389static void request_out_focus(struct stream_out *out, long ns)
390{
391 struct audio_device *adev = out->dev;
392
Haynes Mathew George03c40102016-01-29 17:57:48 -0800393 if (adev->adm_request_focus_v2) {
394 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
395 } else if (adev->adm_request_focus) {
396 adev->adm_request_focus(adev->adm_data, out->handle);
397 }
398}
399
400static void request_in_focus(struct stream_in *in, long ns)
401{
402 struct audio_device *adev = in->dev;
403
Haynes Mathew George03c40102016-01-29 17:57:48 -0800404 if (adev->adm_request_focus_v2) {
405 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
406 } else if (adev->adm_request_focus) {
407 adev->adm_request_focus(adev->adm_data, in->capture_handle);
408 }
409}
410
411static void release_out_focus(struct stream_out *out, long ns __unused)
412{
413 struct audio_device *adev = out->dev;
414
415 if (adev->adm_abandon_focus)
416 adev->adm_abandon_focus(adev->adm_data, out->handle);
417}
418
419static void release_in_focus(struct stream_in *in, long ns __unused)
420{
421 struct audio_device *adev = in->dev;
422 if (adev->adm_abandon_focus)
423 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
424}
425
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700426static int parse_snd_card_status(struct str_parms * parms, int * card,
427 card_status_t * status)
428{
429 char value[32]={0};
430 char state[32]={0};
431
432 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
433
434 if (ret < 0)
435 return -1;
436
437 // sscanf should be okay as value is of max length 32.
438 // same as sizeof state.
439 if (sscanf(value, "%d,%s", card, state) < 2)
440 return -1;
441
442 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
443 CARD_STATUS_OFFLINE;
444 return 0;
445}
446
vivek mehta40125092017-08-21 18:48:51 -0700447// always call with adev lock held
448void send_gain_dep_calibration_l() {
449 if (last_known_cal_step >= 0)
450 platform_send_gain_dep_cal(adev->platform, last_known_cal_step);
451}
452
vivek mehta1a9b7c02015-06-25 11:49:38 -0700453__attribute__ ((visibility ("default")))
454bool audio_hw_send_gain_dep_calibration(int level) {
455 bool ret_val = false;
456 ALOGV("%s: enter ... ", __func__);
457
458 pthread_mutex_lock(&adev_init_lock);
459
460 if (adev != NULL && adev->platform != NULL) {
461 pthread_mutex_lock(&adev->lock);
vivek mehta40125092017-08-21 18:48:51 -0700462 last_known_cal_step = level;
463 send_gain_dep_calibration_l();
vivek mehta1a9b7c02015-06-25 11:49:38 -0700464 pthread_mutex_unlock(&adev->lock);
465 } else {
466 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
467 }
468
469 pthread_mutex_unlock(&adev_init_lock);
470
471 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
472 return ret_val;
473}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700474
vivek mehtaa8d7c922016-05-25 14:40:44 -0700475__attribute__ ((visibility ("default")))
476int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
477 int table_size) {
478 int ret_val = 0;
479 ALOGV("%s: enter ... ", __func__);
480
481 pthread_mutex_lock(&adev_init_lock);
482 if (adev == NULL) {
483 ALOGW("%s: adev is NULL .... ", __func__);
484 goto done;
485 }
486
487 pthread_mutex_lock(&adev->lock);
488 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
489 pthread_mutex_unlock(&adev->lock);
490done:
491 pthread_mutex_unlock(&adev_init_lock);
492 ALOGV("%s: exit ... ", __func__);
493 return ret_val;
494}
495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496static bool is_supported_format(audio_format_t format)
497{
Eric Laurent8251ac82014-07-23 11:00:25 -0700498 switch (format) {
499 case AUDIO_FORMAT_MP3:
500 case AUDIO_FORMAT_AAC_LC:
501 case AUDIO_FORMAT_AAC_HE_V1:
502 case AUDIO_FORMAT_AAC_HE_V2:
503 return true;
504 default:
505 break;
506 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700507 return false;
508}
509
Haynes Mathew George03c40102016-01-29 17:57:48 -0800510static inline bool is_mmap_usecase(audio_usecase_t uc_id)
511{
512 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
513 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
514}
515
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700516static int get_snd_codec_id(audio_format_t format)
517{
518 int id = 0;
519
Eric Laurent8251ac82014-07-23 11:00:25 -0700520 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700521 case AUDIO_FORMAT_MP3:
522 id = SND_AUDIOCODEC_MP3;
523 break;
524 case AUDIO_FORMAT_AAC:
525 id = SND_AUDIOCODEC_AAC;
526 break;
527 default:
528 ALOGE("%s: Unsupported audio format", __func__);
529 }
530
531 return id;
532}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800533
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800534static int audio_ssr_status(struct audio_device *adev)
535{
536 int ret = 0;
537 struct mixer_ctl *ctl;
538 const char *mixer_ctl_name = "Audio SSR Status";
539
540 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
541 ret = mixer_ctl_get_value(ctl, 0);
542 ALOGD("%s: value: %d", __func__, ret);
543 return ret;
544}
545
vivek mehta4a824772017-06-08 19:05:49 -0700546static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
547{
548 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
549}
550
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800551int enable_audio_route(struct audio_device *adev,
552 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800553{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700554 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800556
557 if (usecase == NULL)
558 return -EINVAL;
559
560 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
561
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800562 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800564 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800566
Yamit Mehtae3b99562016-09-16 22:44:00 +0530567 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800568 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800569 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500570 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700571 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700572 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800573
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800574 ALOGV("%s: exit", __func__);
575 return 0;
576}
577
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800578int disable_audio_route(struct audio_device *adev,
579 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800580{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700581 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800583
584 if (usecase == NULL)
585 return -EINVAL;
586
587 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588 if (usecase->type == PCM_CAPTURE)
589 snd_device = usecase->in_snd_device;
590 else
591 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800592 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500593 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700594 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700595 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800597 ALOGV("%s: exit", __func__);
598 return 0;
599}
600
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800601int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700602 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800603{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700604 int i, num_devices = 0;
605 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800606 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800607 if (snd_device < SND_DEVICE_MIN ||
608 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800609 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800610 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800611 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700613 platform_send_audio_calibration(adev->platform, snd_device);
614
vivek mehtade4849c2016-03-03 17:23:38 -0800615 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700616 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700617 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800618 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619 }
620
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700621 /* due to the possibility of calibration overwrite between listen
622 and audio, notify sound trigger hal before audio calibration is sent */
623 audio_extn_sound_trigger_update_device_status(snd_device,
624 ST_EVENT_SND_DEVICE_BUSY);
625
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700626 if (audio_extn_spkr_prot_is_enabled())
627 audio_extn_spkr_prot_calib_cancel(adev);
628
zhaoyang yin4211fad2015-06-04 21:13:25 +0800629 audio_extn_dsm_feedback_enable(adev, snd_device, true);
630
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700631 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800632 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700633 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
634 audio_extn_spkr_prot_is_enabled()) {
635 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800636 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700637 }
638 if (audio_extn_spkr_prot_start_processing(snd_device)) {
639 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800640 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700641 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700642 } else if (platform_can_split_snd_device(snd_device,
643 &num_devices,
644 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700645 for (i = 0; i < num_devices; i++) {
646 enable_snd_device(adev, new_snd_devices[i]);
647 }
vivek mehtab6506412015-08-07 16:55:17 -0700648 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700649 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800650 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
651 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
652 ALOGE(" %s: Invalid sound device returned", __func__);
653 goto on_error;
654 }
Ed Tam70b5c142016-03-21 19:14:29 -0700655
Eric Laurent2e140aa2016-06-30 17:14:46 -0700656 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800657 audio_route_apply_and_update_path(adev->audio_route, device_name);
658 }
659on_success:
660 adev->snd_dev_ref_cnt[snd_device]++;
661 ret_val = 0;
662on_error:
663 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800664}
665
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800666int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700667 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800668{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700669 int i, num_devices = 0;
670 snd_device_t new_snd_devices[2];
671
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800672 if (snd_device < SND_DEVICE_MIN ||
673 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800674 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800675 return -EINVAL;
676 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700677 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
678 ALOGE("%s: device ref cnt is already 0", __func__);
679 return -EINVAL;
680 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800681 audio_extn_tfa_98xx_disable_speaker(snd_device);
682
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 adev->snd_dev_ref_cnt[snd_device]--;
684 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800685 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700686 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800687 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700688 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700689 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
690 audio_extn_spkr_prot_is_enabled()) {
691 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700692
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700693 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
694 // and does not use speaker swap. As this code causes a problem with device enable ref
695 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700696 // when speaker device is disabled, reset swap.
697 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700698 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700699
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700700 } else if (platform_can_split_snd_device(snd_device,
701 &num_devices,
702 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700703 for (i = 0; i < num_devices; i++) {
704 disable_snd_device(adev, new_snd_devices[i]);
705 }
vivek mehtab6506412015-08-07 16:55:17 -0700706 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700707 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800708 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
709 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
710 ALOGE(" %s: Invalid sound device returned", __func__);
711 return -EINVAL;
712 }
713
Eric Laurent2e140aa2016-06-30 17:14:46 -0700714 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800715 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700716 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700717 audio_extn_sound_trigger_update_device_status(snd_device,
718 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700719 }
vivek mehtab6506412015-08-07 16:55:17 -0700720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800721 return 0;
722}
723
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700724/*
725 legend:
726 uc - existing usecase
727 new_uc - new usecase
728 d1, d11, d2 - SND_DEVICE enums
729 a1, a2 - corresponding ANDROID device enums
730 B, B1, B2 - backend strings
731
732case 1
733 uc->dev d1 (a1) B1
734 new_uc->dev d1 (a1), d2 (a2) B1, B2
735
736 resolution: disable and enable uc->dev on d1
737
738case 2
739 uc->dev d1 (a1) B1
740 new_uc->dev d11 (a1) B1
741
742 resolution: need to switch uc since d1 and d11 are related
743 (e.g. speaker and voice-speaker)
744 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
745
746case 3
747 uc->dev d1 (a1) B1
748 new_uc->dev d2 (a2) B2
749
750 resolution: no need to switch uc
751
752case 4
753 uc->dev d1 (a1) B
754 new_uc->dev d2 (a2) B
755
756 resolution: disable enable uc-dev on d2 since backends match
757 we cannot enable two streams on two different devices if they
758 share the same backend. e.g. if offload is on speaker device using
759 QUAD_MI2S backend and a low-latency stream is started on voice-handset
760 using the same backend, offload must also be switched to voice-handset.
761
762case 5
763 uc->dev d1 (a1) B
764 new_uc->dev d1 (a1), d2 (a2) B
765
766 resolution: disable enable uc-dev on d2 since backends match
767 we cannot enable two streams on two different devices if they
768 share the same backend.
769
770case 6
771 uc->dev d1 a1 B1
772 new_uc->dev d2 a1 B2
773
774 resolution: no need to switch
775
776case 7
777
778 uc->dev d1 (a1), d2 (a2) B1, B2
779 new_uc->dev d1 B1
780
781 resolution: no need to switch
782
783*/
784static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
785 struct audio_usecase *new_uc,
786 snd_device_t new_snd_device)
787{
788 audio_devices_t a1 = uc->stream.out->devices;
789 audio_devices_t a2 = new_uc->stream.out->devices;
790
791 snd_device_t d1 = uc->out_snd_device;
792 snd_device_t d2 = new_snd_device;
793
794 // Treat as a special case when a1 and a2 are not disjoint
795 if ((a1 != a2) && (a1 & a2)) {
796 snd_device_t d3[2];
797 int num_devices = 0;
798 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
799 &num_devices,
800 d3);
801 if (ret < 0) {
802 if (ret != -ENOSYS) {
803 ALOGW("%s failed to split snd_device %d",
804 __func__,
805 popcount(a1) > 1 ? d1 : d2);
806 }
807 goto end;
808 }
809
810 // NB: case 7 is hypothetical and isn't a practical usecase yet.
811 // But if it does happen, we need to give priority to d2 if
812 // the combo devices active on the existing usecase share a backend.
813 // This is because we cannot have a usecase active on a combo device
814 // and a new usecase requests one device in this combo pair.
815 if (platform_check_backends_match(d3[0], d3[1])) {
816 return d2; // case 5
817 } else {
818 return d1; // case 1
819 }
820 } else {
821 if (platform_check_backends_match(d1, d2)) {
822 return d2; // case 2, 4
823 } else {
824 return d1; // case 6, 3
825 }
826 }
827
828end:
829 return d2; // return whatever was calculated before.
830}
831
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700832static void check_and_route_playback_usecases(struct audio_device *adev,
833 struct audio_usecase *uc_info,
834 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700835{
836 struct listnode *node;
837 struct audio_usecase *usecase;
838 bool switch_device[AUDIO_USECASE_MAX];
839 int i, num_uc_to_switch = 0;
840
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700841 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
842 uc_info,
843 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700844
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700845 /*
846 * This function is to make sure that all the usecases that are active on
847 * the hardware codec backend are always routed to any one device that is
848 * handled by the hardware codec.
849 * For example, if low-latency and deep-buffer usecases are currently active
850 * on speaker and out_set_parameters(headset) is received on low-latency
851 * output, then we have to make sure deep-buffer is also switched to headset,
852 * because of the limitation that both the devices cannot be enabled
853 * at the same time as they share the same backend.
854 */
855 /* Disable all the usecases on the shared backend other than the
856 specified usecase */
857 for (i = 0; i < AUDIO_USECASE_MAX; i++)
858 switch_device[i] = false;
859
860 list_for_each(node, &adev->usecase_list) {
861 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700862 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
863 continue;
864
865 if (force_routing ||
866 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700867 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
868 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700869 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
871 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700872 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700873 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700874 switch_device[usecase->id] = true;
875 num_uc_to_switch++;
876 }
877 }
878
879 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 list_for_each(node, &adev->usecase_list) {
881 usecase = node_to_item(node, struct audio_usecase, list);
882 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700883 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900884 }
885 }
886
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700887 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900888 list_for_each(node, &adev->usecase_list) {
889 usecase = node_to_item(node, struct audio_usecase, list);
890 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700891 d_device = derive_playback_snd_device(usecase, uc_info,
892 snd_device);
893 enable_snd_device(adev, d_device);
894 /* Update the out_snd_device before enabling the audio route */
895 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700896 }
897 }
898
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 /* Re-route all the usecases on the shared backend other than the
900 specified usecase to new snd devices */
901 list_for_each(node, &adev->usecase_list) {
902 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700903 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700904 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 }
906 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700907 }
908}
909
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700910static void check_and_route_capture_usecases(struct audio_device *adev,
911 struct audio_usecase *uc_info,
912 snd_device_t snd_device)
913{
914 struct listnode *node;
915 struct audio_usecase *usecase;
916 bool switch_device[AUDIO_USECASE_MAX];
917 int i, num_uc_to_switch = 0;
918
vivek mehta4ed66e62016-04-15 23:33:34 -0700919 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
920
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700921 /*
922 * This function is to make sure that all the active capture usecases
923 * are always routed to the same input sound device.
924 * For example, if audio-record and voice-call usecases are currently
925 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
926 * is received for voice call then we have to make sure that audio-record
927 * usecase is also switched to earpiece i.e. voice-dmic-ef,
928 * because of the limitation that two devices cannot be enabled
929 * at the same time if they share the same backend.
930 */
931 for (i = 0; i < AUDIO_USECASE_MAX; i++)
932 switch_device[i] = false;
933
934 list_for_each(node, &adev->usecase_list) {
935 usecase = node_to_item(node, struct audio_usecase, list);
936 if (usecase->type != PCM_PLAYBACK &&
937 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700938 usecase->in_snd_device != snd_device &&
939 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700940 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
941 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700942 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700943 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700944 switch_device[usecase->id] = true;
945 num_uc_to_switch++;
946 }
947 }
948
949 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700950 list_for_each(node, &adev->usecase_list) {
951 usecase = node_to_item(node, struct audio_usecase, list);
952 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700953 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700954 }
955 }
956
957 list_for_each(node, &adev->usecase_list) {
958 usecase = node_to_item(node, struct audio_usecase, list);
959 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700960 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700961 }
962 }
963
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700964 /* Re-route all the usecases on the shared backend other than the
965 specified usecase to new snd devices */
966 list_for_each(node, &adev->usecase_list) {
967 usecase = node_to_item(node, struct audio_usecase, list);
968 /* Update the in_snd_device only before enabling the audio route */
969 if (switch_device[usecase->id] ) {
970 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700971 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700972 }
973 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700974 }
975}
976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700978static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800979{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700980 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700981 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800982
983 switch (channels) {
984 /*
985 * Do not handle stereo output in Multi-channel cases
986 * Stereo case is handled in normal playback path
987 */
988 case 6:
989 ALOGV("%s: HDMI supports 5.1", __func__);
990 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
991 break;
992 case 8:
993 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
994 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
995 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
996 break;
997 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700998 ALOGE("HDMI does not support multi channel playback");
999 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000 break;
1001 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001002 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001003}
1004
Andy Hung18859412017-08-09 11:47:21 -07001005static ssize_t read_usb_sup_sample_rates(bool is_playback,
1006 uint32_t *supported_sample_rates,
1007 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001008{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001009 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1010 supported_sample_rates,
1011 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001012#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001013 for (ssize_t i=0; i<count; i++) {
1014 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1015 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001016 }
1017#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001018 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001019}
1020
Haynes Mathew George569b7482017-05-08 14:44:27 -07001021static int read_usb_sup_channel_masks(bool is_playback,
1022 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001023 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001024{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001025 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001026 int channel_count;
1027 uint32_t num_masks = 0;
1028 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1029 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001030 }
Eric Laurent74b55762017-07-09 17:04:53 -07001031 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001032 // start from 2 channels as framework currently doesn't support mono.
1033 // TODO: consider only supporting channel index masks beyond stereo here.
1034 for (channel_count = FCC_2;
1035 channel_count <= channels && num_masks < max_masks;
1036 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001037 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1038 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001039 for (channel_count = FCC_2;
1040 channel_count <= channels && num_masks < max_masks;
1041 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001042 supported_channel_masks[num_masks++] =
1043 audio_channel_mask_for_index_assignment_from_count(channel_count);
1044 }
1045 } else {
1046 // For capture we report all supported channel masks from 1 channel up.
1047 channel_count = MIN_CHANNEL_COUNT;
1048 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1049 // indexed mask
1050 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1051 supported_channel_masks[num_masks++] =
1052 audio_channel_in_mask_from_count(channel_count);
1053 }
1054 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001055#ifdef NDEBUG
1056 for (size_t i = 0; i < num_masks; ++i) {
1057 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1058 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1059 }
1060#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001061 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001062}
1063
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001064static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001065 audio_format_t *supported_formats,
1066 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001067{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001068 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001069 switch (bitwidth) {
1070 case 24:
1071 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001072 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001073 break;
1074 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001075 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001076 break;
1077 case 16:
1078 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001079 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001080 break;
1081 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001082 ALOGV("%s: %s supported format %d", __func__,
1083 is_playback ? "P" : "C", bitwidth);
1084 return 1;
1085}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001086
Haynes Mathew George569b7482017-05-08 14:44:27 -07001087static int read_usb_sup_params_and_compare(bool is_playback,
1088 audio_format_t *format,
1089 audio_format_t *supported_formats,
1090 uint32_t max_formats,
1091 audio_channel_mask_t *mask,
1092 audio_channel_mask_t *supported_channel_masks,
1093 uint32_t max_masks,
1094 uint32_t *rate,
1095 uint32_t *supported_sample_rates,
1096 uint32_t max_rates) {
1097 int ret = 0;
1098 int num_formats;
1099 int num_masks;
1100 int num_rates;
1101 int i;
1102
1103 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1104 max_formats);
1105 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1106 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001107
Haynes Mathew George569b7482017-05-08 14:44:27 -07001108 num_rates = read_usb_sup_sample_rates(is_playback,
1109 supported_sample_rates, max_rates);
1110
1111#define LUT(table, len, what, dflt) \
1112 for (i=0; i<len && (table[i] != what); i++); \
1113 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1114
1115 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1116 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1117 LUT(supported_sample_rates, num_rates, *rate, 0);
1118
1119#undef LUT
1120 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001121}
1122
Andy Hungd9653bd2017-08-01 19:31:39 -07001123static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1124{
1125 // Check if usb is ready.
1126 // The usb device may have been removed quickly after insertion and hence
1127 // no longer available. This will show up as empty channel masks, or rates.
1128
1129 pthread_mutex_lock(&adev->lock);
1130 uint32_t supported_sample_rate;
1131
1132 // we consider usb ready if we can fetch at least one sample rate.
1133 const bool ready = read_usb_sup_sample_rates(
1134 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1135 pthread_mutex_unlock(&adev->lock);
1136 return ready;
1137}
1138
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001139static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1140{
1141 struct audio_usecase *usecase;
1142 struct listnode *node;
1143
1144 list_for_each(node, &adev->usecase_list) {
1145 usecase = node_to_item(node, struct audio_usecase, list);
1146 if (usecase->type == VOICE_CALL) {
1147 ALOGV("%s: usecase id %d", __func__, usecase->id);
1148 return usecase->id;
1149 }
1150 }
1151 return USECASE_INVALID;
1152}
1153
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001154struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1155 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001156{
1157 struct audio_usecase *usecase;
1158 struct listnode *node;
1159
1160 list_for_each(node, &adev->usecase_list) {
1161 usecase = node_to_item(node, struct audio_usecase, list);
1162 if (usecase->id == uc_id)
1163 return usecase;
1164 }
1165 return NULL;
1166}
1167
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001168int select_devices(struct audio_device *adev,
1169 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001170{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001171 snd_device_t out_snd_device = SND_DEVICE_NONE;
1172 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 struct audio_usecase *usecase = NULL;
1174 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001175 struct audio_usecase *hfp_usecase = NULL;
1176 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001177 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001178 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001179 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1180 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001181
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001182 usecase = get_usecase_from_list(adev, uc_id);
1183 if (usecase == NULL) {
1184 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1185 return -EINVAL;
1186 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001187
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001188 if ((usecase->type == VOICE_CALL) ||
1189 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001190 out_snd_device = platform_get_output_snd_device(adev->platform,
1191 usecase->stream.out->devices);
1192 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001193 usecase->devices = usecase->stream.out->devices;
1194 } else {
1195 /*
1196 * If the voice call is active, use the sound devices of voice call usecase
1197 * so that it would not result any device switch. All the usecases will
1198 * be switched to new device when select_devices() is called for voice call
1199 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001200 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001201 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001202 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001203 vc_usecase = get_usecase_from_list(adev,
1204 get_voice_usecase_id_from_list(adev));
1205 if ((vc_usecase != NULL) &&
1206 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1207 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001208 in_snd_device = vc_usecase->in_snd_device;
1209 out_snd_device = vc_usecase->out_snd_device;
1210 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001211 } else if (audio_extn_hfp_is_active(adev)) {
1212 hfp_ucid = audio_extn_hfp_get_usecase();
1213 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1214 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1215 in_snd_device = hfp_usecase->in_snd_device;
1216 out_snd_device = hfp_usecase->out_snd_device;
1217 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001218 }
1219 if (usecase->type == PCM_PLAYBACK) {
1220 usecase->devices = usecase->stream.out->devices;
1221 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001222 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001223 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001224
Eric Laurentb23d5282013-05-14 15:27:20 -07001225 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001227
1228 if (voip_usecase)
1229 voip_out = voip_usecase->stream.out;
1230
1231 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001232 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001233 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001234 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001235 select_devices(adev, adev->active_input->usecase);
1236 }
1237 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001238 } else if (usecase->type == PCM_CAPTURE) {
1239 usecase->devices = usecase->stream.in->device;
1240 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001241 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001242 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001243 if (adev->active_input &&
1244 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1245 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001246
1247 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1248 USECASE_AUDIO_PLAYBACK_VOIP);
1249
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001250 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001251 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1252 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001253 } else if (voip_usecase) {
1254 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001255 } else if (adev->primary_output) {
1256 out_device = adev->primary_output->devices;
1257 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001258 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001259 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001260 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001261 }
1262 }
1263
1264 if (out_snd_device == usecase->out_snd_device &&
1265 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001266 return 0;
1267 }
1268
Eric Laurent2bafff12016-03-17 12:17:23 -07001269 if (out_snd_device != SND_DEVICE_NONE &&
1270 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1271 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1272 __func__,
1273 use_case_table[uc_id],
1274 adev->last_logged_snd_device[uc_id][0],
1275 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1276 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1277 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1278 -1,
1279 out_snd_device,
1280 platform_get_snd_device_name(out_snd_device),
1281 platform_get_snd_device_acdb_id(out_snd_device));
1282 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1283 }
1284 if (in_snd_device != SND_DEVICE_NONE &&
1285 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1286 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1287 __func__,
1288 use_case_table[uc_id],
1289 adev->last_logged_snd_device[uc_id][1],
1290 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1291 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1292 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1293 -1,
1294 in_snd_device,
1295 platform_get_snd_device_name(in_snd_device),
1296 platform_get_snd_device_acdb_id(in_snd_device));
1297 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1298 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001300 /*
1301 * Limitation: While in call, to do a device switch we need to disable
1302 * and enable both RX and TX devices though one of them is same as current
1303 * device.
1304 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001305 if ((usecase->type == VOICE_CALL) &&
1306 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1307 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001308 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001309 /* Disable sidetone only if voice call already exists */
1310 if (voice_is_call_state_active(adev))
1311 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001312 }
1313
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001314 /* Disable current sound devices */
1315 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001316 disable_audio_route(adev, usecase);
1317 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318 }
1319
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001320 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001321 disable_audio_route(adev, usecase);
1322 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001323 }
1324
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001325 /* Applicable only on the targets that has external modem.
1326 * New device information should be sent to modem before enabling
1327 * the devices to reduce in-call device switch time.
1328 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001329 if ((usecase->type == VOICE_CALL) &&
1330 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1331 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001332 status = platform_switch_voice_call_enable_device_config(adev->platform,
1333 out_snd_device,
1334 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001335 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001336
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001337 /* Enable new sound devices */
1338 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001339 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001340 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001341 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001342 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343 }
1344
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001345 if (in_snd_device != SND_DEVICE_NONE) {
1346 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001347 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001348 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001349
Eric Laurentb23d5282013-05-14 15:27:20 -07001350 if (usecase->type == VOICE_CALL)
1351 status = platform_switch_voice_call_device_post(adev->platform,
1352 out_snd_device,
1353 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001354
sangwoo170731f2013-06-08 15:36:36 +09001355 usecase->in_snd_device = in_snd_device;
1356 usecase->out_snd_device = out_snd_device;
1357
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001358 audio_extn_tfa_98xx_set_mode();
1359
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001360 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001361
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001362 /* Applicable only on the targets that has external modem.
1363 * Enable device command should be sent to modem only after
1364 * enabling voice call mixer controls
1365 */
vivek mehta765eb642015-08-07 19:46:06 -07001366 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001367 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1368 out_snd_device,
1369 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001370 /* Enable sidetone only if voice call already exists */
1371 if (voice_is_call_state_active(adev))
1372 voice_set_sidetone(adev, out_snd_device, true);
1373 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001374
Eric Laurentf4520b02017-09-20 18:31:58 -07001375 if (usecase == voip_usecase) {
1376 struct stream_out *voip_out = voip_usecase->stream.out;
1377 audio_extn_utils_send_app_type_gain(adev,
1378 voip_out->app_type_cfg.app_type,
1379 &voip_out->app_type_cfg.gain[0]);
1380 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001381 return status;
1382}
1383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001384static int stop_input_stream(struct stream_in *in)
1385{
1386 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001387 struct audio_usecase *uc_info;
1388 struct audio_device *adev = in->dev;
1389
Eric Laurent994a6932013-07-17 11:51:42 -07001390 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001391 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001392
1393 if (adev->active_input) {
1394 if (adev->active_input->usecase == in->usecase) {
1395 adev->active_input = NULL;
1396 } else {
1397 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1398 __func__,
1399 use_case_table[adev->active_input->usecase],
1400 use_case_table[in->usecase]);
1401 }
1402 }
1403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404 uc_info = get_usecase_from_list(adev, in->usecase);
1405 if (uc_info == NULL) {
1406 ALOGE("%s: Could not find the usecase (%d) in the list",
1407 __func__, in->usecase);
1408 return -EINVAL;
1409 }
1410
vivek mehta781065c2017-04-04 12:55:01 -07001411 /* Close in-call recording streams */
1412 voice_check_and_stop_incall_rec_usecase(adev, in);
1413
Eric Laurent150dbfe2013-02-27 14:31:02 -08001414 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001415 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001416
1417 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001418 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001419
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001420 list_remove(&uc_info->list);
1421 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001422
Eric Laurent994a6932013-07-17 11:51:42 -07001423 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424 return ret;
1425}
1426
1427int start_input_stream(struct stream_in *in)
1428{
1429 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001430 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001431 struct audio_usecase *uc_info;
1432 struct audio_device *adev = in->dev;
1433
Eric Laurent994a6932013-07-17 11:51:42 -07001434 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001435
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001436 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1437 return -EIO;
1438
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001439 if (in->card_status == CARD_STATUS_OFFLINE ||
1440 adev->card_status == CARD_STATUS_OFFLINE) {
1441 ALOGW("in->card_status or adev->card_status offline, try again");
1442 ret = -EAGAIN;
1443 goto error_config;
1444 }
1445
vivek mehta781065c2017-04-04 12:55:01 -07001446 /* Check if source matches incall recording usecase criteria */
1447 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1448 if (ret)
1449 goto error_config;
1450 else
1451 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1452
Eric Laurentb23d5282013-05-14 15:27:20 -07001453 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001454 if (in->pcm_device_id < 0) {
1455 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1456 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001457 ret = -EINVAL;
1458 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001460
1461 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001462 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1463 uc_info->id = in->usecase;
1464 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001465 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001466 uc_info->devices = in->device;
1467 uc_info->in_snd_device = SND_DEVICE_NONE;
1468 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001470 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001471
Wei Wangf4837d52017-11-21 14:51:20 -08001472 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001473 audio_extn_perf_lock_acquire();
1474
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001476
Eric Laurent0e46adf2016-12-16 12:49:24 -08001477 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001478 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001479 ALOGE("%s: pcm stream not ready", __func__);
1480 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001481 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001482 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001483 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001484 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1485 goto error_open;
1486 }
1487 } else {
1488 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1489 unsigned int pcm_open_retry_count = 0;
1490
1491 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1492 flags |= PCM_MMAP | PCM_NOIRQ;
1493 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1494 } else if (in->realtime) {
1495 flags |= PCM_MMAP | PCM_NOIRQ;
1496 }
1497
1498 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1499 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1500
1501 while (1) {
1502 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1503 flags, &in->config);
1504 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1505 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1506 if (in->pcm != NULL) {
1507 pcm_close(in->pcm);
1508 in->pcm = NULL;
1509 }
1510 if (pcm_open_retry_count-- == 0) {
1511 ret = -EIO;
1512 goto error_open;
1513 }
1514 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1515 continue;
1516 }
1517 break;
1518 }
1519
1520 ALOGV("%s: pcm_prepare", __func__);
1521 ret = pcm_prepare(in->pcm);
1522 if (ret < 0) {
1523 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001524 pcm_close(in->pcm);
1525 in->pcm = NULL;
1526 goto error_open;
1527 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001528 if (in->realtime) {
1529 ret = pcm_start(in->pcm);
1530 if (ret < 0) {
1531 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1532 pcm_close(in->pcm);
1533 in->pcm = NULL;
1534 goto error_open;
1535 }
1536 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001537 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001538 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001539 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001540 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001541 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001542
Eric Laurent0e46adf2016-12-16 12:49:24 -08001543 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001544
1545error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001547 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001548 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001549
1550error_config:
1551 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001552 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001553 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001554}
1555
Eric Laurenta1478072015-09-21 17:21:52 -07001556void lock_input_stream(struct stream_in *in)
1557{
1558 pthread_mutex_lock(&in->pre_lock);
1559 pthread_mutex_lock(&in->lock);
1560 pthread_mutex_unlock(&in->pre_lock);
1561}
1562
1563void lock_output_stream(struct stream_out *out)
1564{
1565 pthread_mutex_lock(&out->pre_lock);
1566 pthread_mutex_lock(&out->lock);
1567 pthread_mutex_unlock(&out->pre_lock);
1568}
1569
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001570/* must be called with out->lock locked */
1571static int send_offload_cmd_l(struct stream_out* out, int command)
1572{
1573 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1574
1575 ALOGVV("%s %d", __func__, command);
1576
1577 cmd->cmd = command;
1578 list_add_tail(&out->offload_cmd_list, &cmd->node);
1579 pthread_cond_signal(&out->offload_cond);
1580 return 0;
1581}
1582
1583/* must be called iwth out->lock locked */
1584static void stop_compressed_output_l(struct stream_out *out)
1585{
1586 out->offload_state = OFFLOAD_STATE_IDLE;
1587 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001588 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001589 if (out->compr != NULL) {
1590 compress_stop(out->compr);
1591 while (out->offload_thread_blocked) {
1592 pthread_cond_wait(&out->cond, &out->lock);
1593 }
1594 }
1595}
1596
1597static void *offload_thread_loop(void *context)
1598{
1599 struct stream_out *out = (struct stream_out *) context;
1600 struct listnode *item;
1601
1602 out->offload_state = OFFLOAD_STATE_IDLE;
1603 out->playback_started = 0;
1604
1605 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1606 set_sched_policy(0, SP_FOREGROUND);
1607 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1608
1609 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001610 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001611 for (;;) {
1612 struct offload_cmd *cmd = NULL;
1613 stream_callback_event_t event;
1614 bool send_callback = false;
1615
1616 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1617 __func__, list_empty(&out->offload_cmd_list),
1618 out->offload_state);
1619 if (list_empty(&out->offload_cmd_list)) {
1620 ALOGV("%s SLEEPING", __func__);
1621 pthread_cond_wait(&out->offload_cond, &out->lock);
1622 ALOGV("%s RUNNING", __func__);
1623 continue;
1624 }
1625
1626 item = list_head(&out->offload_cmd_list);
1627 cmd = node_to_item(item, struct offload_cmd, node);
1628 list_remove(item);
1629
1630 ALOGVV("%s STATE %d CMD %d out->compr %p",
1631 __func__, out->offload_state, cmd->cmd, out->compr);
1632
1633 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1634 free(cmd);
1635 break;
1636 }
1637
1638 if (out->compr == NULL) {
1639 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001640 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001641 pthread_cond_signal(&out->cond);
1642 continue;
1643 }
1644 out->offload_thread_blocked = true;
1645 pthread_mutex_unlock(&out->lock);
1646 send_callback = false;
1647 switch(cmd->cmd) {
1648 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1649 compress_wait(out->compr, -1);
1650 send_callback = true;
1651 event = STREAM_CBK_EVENT_WRITE_READY;
1652 break;
1653 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001654 compress_next_track(out->compr);
1655 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001656 send_callback = true;
1657 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001658 /* Resend the metadata for next iteration */
1659 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001660 break;
1661 case OFFLOAD_CMD_DRAIN:
1662 compress_drain(out->compr);
1663 send_callback = true;
1664 event = STREAM_CBK_EVENT_DRAIN_READY;
1665 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001666 case OFFLOAD_CMD_ERROR:
1667 send_callback = true;
1668 event = STREAM_CBK_EVENT_ERROR;
1669 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001670 default:
1671 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1672 break;
1673 }
Eric Laurenta1478072015-09-21 17:21:52 -07001674 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001675 out->offload_thread_blocked = false;
1676 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001677 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001678 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001679 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001680 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001681 free(cmd);
1682 }
1683
1684 pthread_cond_signal(&out->cond);
1685 while (!list_empty(&out->offload_cmd_list)) {
1686 item = list_head(&out->offload_cmd_list);
1687 list_remove(item);
1688 free(node_to_item(item, struct offload_cmd, node));
1689 }
1690 pthread_mutex_unlock(&out->lock);
1691
1692 return NULL;
1693}
1694
1695static int create_offload_callback_thread(struct stream_out *out)
1696{
1697 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1698 list_init(&out->offload_cmd_list);
1699 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1700 offload_thread_loop, out);
1701 return 0;
1702}
1703
1704static int destroy_offload_callback_thread(struct stream_out *out)
1705{
Eric Laurenta1478072015-09-21 17:21:52 -07001706 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001707 stop_compressed_output_l(out);
1708 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1709
1710 pthread_mutex_unlock(&out->lock);
1711 pthread_join(out->offload_thread, (void **) NULL);
1712 pthread_cond_destroy(&out->offload_cond);
1713
1714 return 0;
1715}
1716
Eric Laurent07eeafd2013-10-06 12:52:49 -07001717static bool allow_hdmi_channel_config(struct audio_device *adev)
1718{
1719 struct listnode *node;
1720 struct audio_usecase *usecase;
1721 bool ret = true;
1722
1723 list_for_each(node, &adev->usecase_list) {
1724 usecase = node_to_item(node, struct audio_usecase, list);
1725 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1726 /*
1727 * If voice call is already existing, do not proceed further to avoid
1728 * disabling/enabling both RX and TX devices, CSD calls, etc.
1729 * Once the voice call done, the HDMI channels can be configured to
1730 * max channels of remaining use cases.
1731 */
1732 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001733 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001734 __func__);
1735 ret = false;
1736 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001737 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1738 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001739 "no change in HDMI channels", __func__);
1740 ret = false;
1741 break;
1742 }
1743 }
1744 }
1745 return ret;
1746}
1747
1748static int check_and_set_hdmi_channels(struct audio_device *adev,
1749 unsigned int channels)
1750{
1751 struct listnode *node;
1752 struct audio_usecase *usecase;
1753
1754 /* Check if change in HDMI channel config is allowed */
1755 if (!allow_hdmi_channel_config(adev))
1756 return 0;
1757
1758 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001759 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001760 return 0;
1761 }
1762
1763 platform_set_hdmi_channels(adev->platform, channels);
1764 adev->cur_hdmi_channels = channels;
1765
1766 /*
1767 * Deroute all the playback streams routed to HDMI so that
1768 * the back end is deactivated. Note that backend will not
1769 * be deactivated if any one stream is connected to it.
1770 */
1771 list_for_each(node, &adev->usecase_list) {
1772 usecase = node_to_item(node, struct audio_usecase, list);
1773 if (usecase->type == PCM_PLAYBACK &&
1774 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001775 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001776 }
1777 }
1778
1779 /*
1780 * Enable all the streams disabled above. Now the HDMI backend
1781 * will be activated with new channel configuration
1782 */
1783 list_for_each(node, &adev->usecase_list) {
1784 usecase = node_to_item(node, struct audio_usecase, list);
1785 if (usecase->type == PCM_PLAYBACK &&
1786 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001787 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001788 }
1789 }
1790
1791 return 0;
1792}
1793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794static int stop_output_stream(struct stream_out *out)
1795{
1796 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797 struct audio_usecase *uc_info;
1798 struct audio_device *adev = out->dev;
1799
Eric Laurent994a6932013-07-17 11:51:42 -07001800 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001801 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001802 uc_info = get_usecase_from_list(adev, out->usecase);
1803 if (uc_info == NULL) {
1804 ALOGE("%s: Could not find the usecase (%d) in the list",
1805 __func__, out->usecase);
1806 return -EINVAL;
1807 }
1808
Haynes Mathew George41f86652014-06-17 14:22:15 -07001809 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1810 if (adev->visualizer_stop_output != NULL)
1811 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1812 if (adev->offload_effects_stop_output != NULL)
1813 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001814 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1815 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1816 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001817 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001818
Eric Laurent150dbfe2013-02-27 14:31:02 -08001819 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001820 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001821
1822 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001823 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001825 list_remove(&uc_info->list);
1826 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827
Eric Laurent0499d4f2014-08-25 22:39:29 -05001828 audio_extn_extspk_update(adev->extspk);
1829
Eric Laurent07eeafd2013-10-06 12:52:49 -07001830 /* Must be called after removing the usecase from list */
1831 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1832 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001833 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1834 struct listnode *node;
1835 struct audio_usecase *usecase;
1836 list_for_each(node, &adev->usecase_list) {
1837 usecase = node_to_item(node, struct audio_usecase, list);
1838 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1839 select_devices(adev, usecase->id);
1840 }
1841 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001842
Eric Laurent994a6932013-07-17 11:51:42 -07001843 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001844 return ret;
1845}
1846
1847int start_output_stream(struct stream_out *out)
1848{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001849 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 struct audio_usecase *uc_info;
1851 struct audio_device *adev = out->dev;
1852
Eric Laurent994a6932013-07-17 11:51:42 -07001853 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001854 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001855
1856 if (out->card_status == CARD_STATUS_OFFLINE ||
1857 adev->card_status == CARD_STATUS_OFFLINE) {
1858 ALOGW("out->card_status or adev->card_status offline, try again");
1859 ret = -EAGAIN;
1860 goto error_config;
1861 }
1862
Eric Laurentb23d5282013-05-14 15:27:20 -07001863 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864 if (out->pcm_device_id < 0) {
1865 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1866 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001867 ret = -EINVAL;
1868 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 }
1870
1871 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1872 uc_info->id = out->usecase;
1873 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001874 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001875 uc_info->devices = out->devices;
1876 uc_info->in_snd_device = SND_DEVICE_NONE;
1877 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878
Eric Laurent07eeafd2013-10-06 12:52:49 -07001879 /* This must be called before adding this usecase to the list */
1880 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1881 check_and_set_hdmi_channels(adev, out->config.channels);
1882
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001883 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884
Wei Wangf4837d52017-11-21 14:51:20 -08001885 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001886 audio_extn_perf_lock_acquire();
1887
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001888 select_devices(adev, out->usecase);
1889
Eric Laurent0499d4f2014-08-25 22:39:29 -05001890 audio_extn_extspk_update(adev->extspk);
1891
Andy Hung31aca912014-03-20 17:14:59 -07001892 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001893 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001894 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1895 out->pcm = NULL;
1896 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1897 COMPRESS_IN, &out->compr_config);
1898 if (out->compr && !is_compress_ready(out->compr)) {
1899 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1900 compress_close(out->compr);
1901 out->compr = NULL;
1902 ret = -EIO;
1903 goto error_open;
1904 }
1905 if (out->offload_callback)
1906 compress_nonblock(out->compr, out->non_blocking);
1907
1908 if (adev->visualizer_start_output != NULL)
1909 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1910 if (adev->offload_effects_start_output != NULL)
1911 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1912 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001913 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001914 ALOGE("%s: pcm stream not ready", __func__);
1915 goto error_open;
1916 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001917 ret = pcm_start(out->pcm);
1918 if (ret < 0) {
1919 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1920 goto error_open;
1921 }
1922 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001923 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001924 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001925
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001926 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1927 flags |= PCM_MMAP | PCM_NOIRQ;
1928 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001929 } else if (out->realtime) {
1930 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001931 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001932
1933 while (1) {
1934 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1935 flags, &out->config);
1936 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1937 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1938 if (out->pcm != NULL) {
1939 pcm_close(out->pcm);
1940 out->pcm = NULL;
1941 }
1942 if (pcm_open_retry_count-- == 0) {
1943 ret = -EIO;
1944 goto error_open;
1945 }
1946 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1947 continue;
1948 }
1949 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001950 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001951 ALOGV("%s: pcm_prepare", __func__);
1952 if (pcm_is_ready(out->pcm)) {
1953 ret = pcm_prepare(out->pcm);
1954 if (ret < 0) {
1955 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1956 pcm_close(out->pcm);
1957 out->pcm = NULL;
1958 goto error_open;
1959 }
1960 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001961 if (out->realtime) {
1962 ret = pcm_start(out->pcm);
1963 if (ret < 0) {
1964 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1965 pcm_close(out->pcm);
1966 out->pcm = NULL;
1967 goto error_open;
1968 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001969 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001970 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001971 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08001972 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001973 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001974 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07001975
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001976 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1977 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1978 audio_low_latency_hint_start();
1979 }
1980
vivek mehtae59cfb22017-06-16 15:57:11 -07001981 // consider a scenario where on pause lower layers are tear down.
1982 // so on resume, swap mixer control need to be sent only when
1983 // backend is active, hence rather than sending from enable device
1984 // sending it from start of streamtream
1985
1986 platform_set_swap_channels(adev, true);
1987
Eric Laurent994a6932013-07-17 11:51:42 -07001988 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001989 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001990error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08001991 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001992 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001994error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001995 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996}
1997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998static int check_input_parameters(uint32_t sample_rate,
1999 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002000 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002001{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002002 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2003 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002004 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2005 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002006 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2007 return -EINVAL;
2008 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002009
Eric Laurent74b55762017-07-09 17:04:53 -07002010 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2011 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002012 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002013 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002014 return -EINVAL;
2015 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002016
2017 switch (sample_rate) {
2018 case 8000:
2019 case 11025:
2020 case 12000:
2021 case 16000:
2022 case 22050:
2023 case 24000:
2024 case 32000:
2025 case 44100:
2026 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002027 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002028 break;
2029 default:
vivek mehtadae44712015-07-27 14:13:18 -07002030 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031 return -EINVAL;
2032 }
2033
2034 return 0;
2035}
2036
vivek mehtaa68fea62017-06-08 19:04:02 -07002037static size_t get_stream_buffer_size(size_t duration_ms,
2038 uint32_t sample_rate,
2039 audio_format_t format,
2040 int channel_count,
2041 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002042{
2043 size_t size = 0;
2044
vivek mehtaa68fea62017-06-08 19:04:02 -07002045 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002046 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002047 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002048
2049 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002050
Glenn Kasten4f993392014-05-14 07:30:48 -07002051 /* make sure the size is multiple of 32 bytes
2052 * At 48 kHz mono 16-bit PCM:
2053 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2054 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2055 */
2056 size += 0x1f;
2057 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002058
2059 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060}
2061
2062static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2063{
2064 struct stream_out *out = (struct stream_out *)stream;
2065
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002066 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002067}
2068
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002069static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070{
2071 return -ENOSYS;
2072}
2073
2074static size_t out_get_buffer_size(const struct audio_stream *stream)
2075{
2076 struct stream_out *out = (struct stream_out *)stream;
2077
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002078 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2079 return out->compr_config.fragment_size;
2080 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002081 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002082 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002083}
2084
2085static uint32_t out_get_channels(const struct audio_stream *stream)
2086{
2087 struct stream_out *out = (struct stream_out *)stream;
2088
2089 return out->channel_mask;
2090}
2091
2092static audio_format_t out_get_format(const struct audio_stream *stream)
2093{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002094 struct stream_out *out = (struct stream_out *)stream;
2095
2096 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097}
2098
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002099static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002100{
2101 return -ENOSYS;
2102}
2103
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002104/* must be called with out->lock locked */
2105static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106{
2107 struct stream_out *out = (struct stream_out *)stream;
2108 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002109 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002111 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002112 if (adev->adm_deregister_stream)
2113 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002114 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002116 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2117 if (out->pcm) {
2118 pcm_close(out->pcm);
2119 out->pcm = NULL;
2120 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002121 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002122 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002123 out->playback_started = false;
2124 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002125 } else {
2126 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002127 out->gapless_mdata.encoder_delay = 0;
2128 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002129 if (out->compr != NULL) {
2130 compress_close(out->compr);
2131 out->compr = NULL;
2132 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002133 }
Phil Burkbc991042017-02-24 08:06:44 -08002134 if (do_stop) {
2135 stop_output_stream(out);
2136 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002137 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002138 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002139 return 0;
2140}
2141
2142static int out_standby(struct audio_stream *stream)
2143{
2144 struct stream_out *out = (struct stream_out *)stream;
2145
2146 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2147 out->usecase, use_case_table[out->usecase]);
2148
2149 lock_output_stream(out);
2150 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002152 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 return 0;
2154}
2155
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002156static int out_on_error(struct audio_stream *stream)
2157{
2158 struct stream_out *out = (struct stream_out *)stream;
2159 struct audio_device *adev = out->dev;
2160 bool do_standby = false;
2161
2162 lock_output_stream(out);
2163 if (!out->standby) {
2164 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2165 stop_compressed_output_l(out);
2166 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2167 } else
2168 do_standby = true;
2169 }
2170 pthread_mutex_unlock(&out->lock);
2171
2172 if (do_standby)
2173 return out_standby(&out->stream.common);
2174
2175 return 0;
2176}
2177
Andy Hung7401c7c2016-09-21 12:41:21 -07002178static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179{
Andy Hung7401c7c2016-09-21 12:41:21 -07002180 struct stream_out *out = (struct stream_out *)stream;
2181
2182 // We try to get the lock for consistency,
2183 // but it isn't necessary for these variables.
2184 // If we're not in standby, we may be blocked on a write.
2185 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2186 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2187 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2188
2189 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002190 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002191 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002192
2193 // dump error info
2194 (void)error_log_dump(
2195 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002196
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002197 return 0;
2198}
2199
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002200static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2201{
2202 int ret = 0;
2203 char value[32];
2204 struct compr_gapless_mdata tmp_mdata;
2205
2206 if (!out || !parms) {
2207 return -EINVAL;
2208 }
2209
2210 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2211 if (ret >= 0) {
2212 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2213 } else {
2214 return -EINVAL;
2215 }
2216
2217 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2218 if (ret >= 0) {
2219 tmp_mdata.encoder_padding = atoi(value);
2220 } else {
2221 return -EINVAL;
2222 }
2223
2224 out->gapless_mdata = tmp_mdata;
2225 out->send_new_metadata = 1;
2226 ALOGV("%s new encoder delay %u and padding %u", __func__,
2227 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2228
2229 return 0;
2230}
2231
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002232static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2233{
2234 return out == adev->primary_output || out == adev->voice_tx_output;
2235}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002236
Kevin Rocard1e02c882017-08-09 15:26:07 -07002237static int get_alive_usb_card(struct str_parms* parms) {
2238 int card;
2239 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2240 !audio_extn_usb_alive(card)) {
2241 return card;
2242 }
2243 return -ENODEV;
2244}
2245
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2247{
2248 struct stream_out *out = (struct stream_out *)stream;
2249 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002250 struct audio_usecase *usecase;
2251 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002252 struct str_parms *parms;
2253 char value[32];
2254 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002255 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002256 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002257
Eric Laurent2e140aa2016-06-30 17:14:46 -07002258 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002259 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 parms = str_parms_create_str(kvpairs);
2261 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2262 if (ret >= 0) {
2263 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002264
Eric Laurenta1478072015-09-21 17:21:52 -07002265 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002266
2267 // The usb driver needs to be closed after usb device disconnection
2268 // otherwise audio is no longer played on the new usb devices.
2269 // By forcing the stream in standby, the usb stack refcount drops to 0
2270 // and the driver is closed.
2271 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2272 audio_is_usb_out_device(out->devices)) {
2273 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2274 out_standby_l(&out->stream.common);
2275 }
2276
Eric Laurent150dbfe2013-02-27 14:31:02 -08002277 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002279 /*
2280 * When HDMI cable is unplugged the music playback is paused and
2281 * the policy manager sends routing=0. But the audioflinger
2282 * continues to write data until standby time (3sec).
2283 * As the HDMI core is turned off, the write gets blocked.
2284 * Avoid this by routing audio to speaker until standby.
2285 */
2286 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2287 val == AUDIO_DEVICE_NONE) {
2288 val = AUDIO_DEVICE_OUT_SPEAKER;
2289 }
2290
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002291 audio_devices_t new_dev = val;
2292
2293 // Workaround: If routing to an non existing usb device, fail gracefully
2294 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002295 int card;
2296 if (audio_is_usb_out_device(new_dev) &&
2297 (card = get_alive_usb_card(parms)) >= 0) {
2298
2299 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002300 pthread_mutex_unlock(&adev->lock);
2301 pthread_mutex_unlock(&out->lock);
2302 status = -ENOSYS;
2303 goto routing_fail;
2304 }
2305
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002306 /*
2307 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002308 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002309 * the select_devices(). But how do we undo this?
2310 *
2311 * For example, music playback is active on headset (deep-buffer usecase)
2312 * and if we go to ringtones and select a ringtone, low-latency usecase
2313 * will be started on headset+speaker. As we can't enable headset+speaker
2314 * and headset devices at the same time, select_devices() switches the music
2315 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2316 * So when the ringtone playback is completed, how do we undo the same?
2317 *
2318 * We are relying on the out_set_parameters() call on deep-buffer output,
2319 * once the ringtone playback is ended.
2320 * NOTE: We should not check if the current devices are same as new devices.
2321 * Because select_devices() must be called to switch back the music
2322 * playback to headset.
2323 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002324 if (new_dev != AUDIO_DEVICE_NONE) {
2325 bool same_dev = out->devices == new_dev;
2326 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002327
Eric Laurenta7657192014-10-09 21:09:33 -07002328 if (output_drives_call(adev, out)) {
2329 if (!voice_is_in_call(adev)) {
2330 if (adev->mode == AUDIO_MODE_IN_CALL) {
2331 adev->current_call_output = out;
2332 ret = voice_start_call(adev);
2333 }
2334 } else {
2335 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002336 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002337 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002338 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002339
2340 if (!out->standby) {
2341 if (!same_dev) {
2342 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002343 // inform adm before actual routing to prevent glitches.
2344 if (adev->adm_on_routing_change) {
2345 adev->adm_on_routing_change(adev->adm_data,
2346 out->handle);
2347 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002348 }
2349 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002350 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002351
2352 // on device switch force swap, lower functions will make sure
2353 // to check if swap is allowed or not.
2354
2355 if (!same_dev)
2356 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002357 }
2358
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002359 }
2360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002362 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002363
2364 /*handles device and call state changes*/
2365 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002366 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002367 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002368
2369 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2370 parse_compress_metadata(out, parms);
2371 }
2372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002374 ALOGV("%s: exit: code(%d)", __func__, status);
2375 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376}
2377
Haynes Mathew George569b7482017-05-08 14:44:27 -07002378static bool stream_get_parameter_channels(struct str_parms *query,
2379 struct str_parms *reply,
2380 audio_channel_mask_t *supported_channel_masks) {
2381 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002384 size_t i, j;
2385
2386 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2387 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388 value[0] = '\0';
2389 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002390 while (supported_channel_masks[i] != 0) {
2391 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2392 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393 if (!first) {
2394 strcat(value, "|");
2395 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002396 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 first = false;
2398 break;
2399 }
2400 }
2401 i++;
2402 }
2403 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002404 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002405 return ret >= 0;
2406}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002407
Haynes Mathew George569b7482017-05-08 14:44:27 -07002408static bool stream_get_parameter_formats(struct str_parms *query,
2409 struct str_parms *reply,
2410 audio_format_t *supported_formats) {
2411 int ret = -1;
2412 char value[256];
2413 int i;
2414
2415 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2416 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002417 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002418 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002419 case AUDIO_FORMAT_PCM_16_BIT:
2420 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2421 break;
2422 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2423 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2424 break;
2425 case AUDIO_FORMAT_PCM_32_BIT:
2426 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2427 break;
2428 default:
2429 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002430 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002431 break;
2432 }
2433 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002434 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002435 return ret >= 0;
2436}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002437
Haynes Mathew George569b7482017-05-08 14:44:27 -07002438static bool stream_get_parameter_rates(struct str_parms *query,
2439 struct str_parms *reply,
2440 uint32_t *supported_sample_rates) {
2441
2442 int i;
2443 char value[256];
2444 int ret = -1;
2445 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2446 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002447 value[0] = '\0';
2448 i=0;
2449 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002450 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002451 int avail = sizeof(value) - cursor;
2452 ret = snprintf(value + cursor, avail, "%s%d",
2453 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002454 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002455 if (ret < 0 || ret >= avail) {
2456 // if cursor is at the last element of the array
2457 // overwrite with \0 is duplicate work as
2458 // snprintf already put a \0 in place.
2459 // else
2460 // we had space to write the '|' at value[cursor]
2461 // (which will be overwritten) or no space to fill
2462 // the first element (=> cursor == 0)
2463 value[cursor] = '\0';
2464 break;
2465 }
2466 cursor += ret;
2467 ++i;
2468 }
2469 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2470 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002471 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002472 return ret >= 0;
2473}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002474
Haynes Mathew George569b7482017-05-08 14:44:27 -07002475static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2476{
2477 struct stream_out *out = (struct stream_out *)stream;
2478 struct str_parms *query = str_parms_create_str(keys);
2479 char *str;
2480 struct str_parms *reply = str_parms_create();
2481 bool replied = false;
2482 ALOGV("%s: enter: keys - %s", __func__, keys);
2483
2484 replied |= stream_get_parameter_channels(query, reply,
2485 &out->supported_channel_masks[0]);
2486 replied |= stream_get_parameter_formats(query, reply,
2487 &out->supported_formats[0]);
2488 replied |= stream_get_parameter_rates(query, reply,
2489 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002490 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 str = str_parms_to_str(reply);
2492 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002493 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002494 }
2495 str_parms_destroy(query);
2496 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002497 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 return str;
2499}
2500
2501static uint32_t out_get_latency(const struct audio_stream_out *stream)
2502{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002503 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 struct stream_out *out = (struct stream_out *)stream;
2505
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002506 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2507 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002508 else if ((out->realtime) ||
2509 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002510 // since the buffer won't be filled up faster than realtime,
2511 // return a smaller number
2512 period_ms = (out->af_period_multiplier * out->config.period_size *
2513 1000) / (out->config.rate);
2514 hw_delay = platform_render_latency(out->usecase)/1000;
2515 return period_ms + hw_delay;
2516 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002517
2518 return (out->config.period_count * out->config.period_size * 1000) /
2519 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520}
2521
2522static int out_set_volume(struct audio_stream_out *stream, float left,
2523 float right)
2524{
Eric Laurenta9024de2013-04-04 09:19:12 -07002525 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002526 int volume[2];
2527
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002528 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002529 /* only take left channel into account: the API is for stereo anyway */
2530 out->muted = (left == 0.0f);
2531 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002532 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2533 const char *mixer_ctl_name = "Compress Playback Volume";
2534 struct audio_device *adev = out->dev;
2535 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002536 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2537 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002538 /* try with the control based on device id */
2539 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2540 PCM_PLAYBACK);
2541 char ctl_name[128] = {0};
2542 snprintf(ctl_name, sizeof(ctl_name),
2543 "Compress Playback %d Volume", pcm_device_id);
2544 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2545 if (!ctl) {
2546 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2547 return -EINVAL;
2548 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002549 }
2550 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2551 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2552 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2553 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002554 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002555 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2556 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2557 if (!out->standby) {
2558 // if in standby, cached volume will be sent after stream is opened
2559 audio_extn_utils_send_app_type_gain(out->dev,
2560 out->app_type_cfg.app_type,
2561 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002562 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002563 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002564 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002565
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566 return -ENOSYS;
2567}
2568
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002569// note: this call is safe only if the stream_cb is
2570// removed first in close_output_stream (as is done now).
2571static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2572{
2573 if (!stream || !parms)
2574 return;
2575
2576 struct stream_out *out = (struct stream_out *)stream;
2577 struct audio_device *adev = out->dev;
2578
2579 card_status_t status;
2580 int card;
2581 if (parse_snd_card_status(parms, &card, &status) < 0)
2582 return;
2583
2584 pthread_mutex_lock(&adev->lock);
2585 bool valid_cb = (card == adev->snd_card);
2586 pthread_mutex_unlock(&adev->lock);
2587
2588 if (!valid_cb)
2589 return;
2590
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002591 lock_output_stream(out);
2592 if (out->card_status != status)
2593 out->card_status = status;
2594 pthread_mutex_unlock(&out->lock);
2595
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002596 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2597 use_case_table[out->usecase],
2598 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2599
2600 if (status == CARD_STATUS_OFFLINE)
2601 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002602
2603 return;
2604}
2605
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002606#ifdef NO_AUDIO_OUT
2607static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002608 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002609{
2610 struct stream_out *out = (struct stream_out *)stream;
2611
2612 /* No Output device supported other than BT for playback.
2613 * Sleep for the amount of buffer duration
2614 */
Eric Laurenta1478072015-09-21 17:21:52 -07002615 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002616 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2617 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002618 out_get_sample_rate(&out->stream.common));
2619 pthread_mutex_unlock(&out->lock);
2620 return bytes;
2621}
2622#endif
2623
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2625 size_t bytes)
2626{
2627 struct stream_out *out = (struct stream_out *)stream;
2628 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002629 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002630 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631
Eric Laurenta1478072015-09-21 17:21:52 -07002632 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002633 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002634 const size_t frame_size = audio_stream_out_frame_size(stream);
2635 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002636
Eric Laurent0e46adf2016-12-16 12:49:24 -08002637 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2638 error_code = ERROR_CODE_WRITE;
2639 goto exit;
2640 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002642 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002643 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002645
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002646 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002648 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002649 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 goto exit;
2651 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002652
vivek mehta40125092017-08-21 18:48:51 -07002653 // after standby always force set last known cal step
2654 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2655 ALOGD("%s: retry previous failed cal level set", __func__);
2656 send_gain_dep_calibration_l();
2657 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002660 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002661 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002662 if (out->send_new_metadata) {
2663 ALOGVV("send new gapless metadata");
2664 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2665 out->send_new_metadata = 0;
2666 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002667 unsigned int avail;
2668 struct timespec tstamp;
2669 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2670 /* Do not limit write size if the available frames count is unknown */
2671 if (ret != 0) {
2672 avail = bytes;
2673 }
2674 if (avail == 0) {
2675 ret = 0;
2676 } else {
2677 if (avail > bytes) {
2678 avail = bytes;
2679 }
2680 ret = compress_write(out->compr, buffer, avail);
2681 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2682 __func__, avail, ret);
2683 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002684
Eric Laurent6e895242013-09-05 16:10:57 -07002685 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002686 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2687 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002688 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002689 compress_start(out->compr);
2690 out->playback_started = 1;
2691 out->offload_state = OFFLOAD_STATE_PLAYING;
2692 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002693 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002694 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002695 } else {
2696 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002697 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002698 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002699 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002700 return ret;
2701 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002702 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002703 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002704 size_t bytes_to_write = bytes;
2705
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002706 if (out->muted)
2707 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002708 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02002709 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002710 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2711 int16_t *src = (int16_t *)buffer;
2712 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002713
Eric Laurentad2dde92017-09-20 18:27:31 -07002714 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2715 out->format != AUDIO_FORMAT_PCM_16_BIT,
2716 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002717
Eric Laurentad2dde92017-09-20 18:27:31 -07002718 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2719 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2720 }
2721 bytes_to_write /= 2;
2722 }
2723 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2724
Glenn Kasten5a59dff2018-02-22 08:05:35 -08002725 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002726 request_out_focus(out, ns);
2727
2728 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2729 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002730 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002731 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002732 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002733
Haynes Mathew George03c40102016-01-29 17:57:48 -08002734 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002735 } else {
2736 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002737 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738 }
2739
2740exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002741 // For PCM we always consume the buffer and return #bytes regardless of ret.
2742 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002743 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002744 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002745 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002746
Andy Hung7401c7c2016-09-21 12:41:21 -07002747 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002748 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002749 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2750 ALOGE_IF(out->pcm != NULL,
2751 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002752 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002753 // usleep not guaranteed for values over 1 second but we don't limit here.
2754 }
2755 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757 pthread_mutex_unlock(&out->lock);
2758
2759 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002760 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002761 if (sleeptime_us != 0)
2762 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763 }
2764 return bytes;
2765}
2766
2767static int out_get_render_position(const struct audio_stream_out *stream,
2768 uint32_t *dsp_frames)
2769{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002770 struct stream_out *out = (struct stream_out *)stream;
2771 *dsp_frames = 0;
2772 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002773 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002774 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002775 unsigned long frames = 0;
2776 // TODO: check return value
2777 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2778 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002779 ALOGVV("%s rendered frames %d sample_rate %d",
2780 __func__, *dsp_frames, out->sample_rate);
2781 }
2782 pthread_mutex_unlock(&out->lock);
2783 return 0;
2784 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002785 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002786}
2787
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002788static int out_add_audio_effect(const struct audio_stream *stream __unused,
2789 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790{
2791 return 0;
2792}
2793
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002794static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2795 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796{
2797 return 0;
2798}
2799
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002800static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2801 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002803 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804}
2805
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002806static int out_get_presentation_position(const struct audio_stream_out *stream,
2807 uint64_t *frames, struct timespec *timestamp)
2808{
2809 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002810 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002811 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002812
Eric Laurenta1478072015-09-21 17:21:52 -07002813 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002814
Eric Laurent949a0892013-09-20 09:20:13 -07002815 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2816 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002817 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002818 compress_get_tstamp(out->compr, &dsp_frames,
2819 &out->sample_rate);
2820 ALOGVV("%s rendered frames %ld sample_rate %d",
2821 __func__, dsp_frames, out->sample_rate);
2822 *frames = dsp_frames;
2823 ret = 0;
2824 /* this is the best we can do */
2825 clock_gettime(CLOCK_MONOTONIC, timestamp);
2826 }
2827 } else {
2828 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002829 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002830 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2831 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002832 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002833 // This adjustment accounts for buffering after app processor.
2834 // It is based on estimated DSP latency per use case, rather than exact.
2835 signed_frames -=
2836 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2837
Eric Laurent949a0892013-09-20 09:20:13 -07002838 // It would be unusual for this value to be negative, but check just in case ...
2839 if (signed_frames >= 0) {
2840 *frames = signed_frames;
2841 ret = 0;
2842 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002843 }
2844 }
2845 }
2846
2847 pthread_mutex_unlock(&out->lock);
2848
2849 return ret;
2850}
2851
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002852static int out_set_callback(struct audio_stream_out *stream,
2853 stream_callback_t callback, void *cookie)
2854{
2855 struct stream_out *out = (struct stream_out *)stream;
2856
2857 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002858 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859 out->offload_callback = callback;
2860 out->offload_cookie = cookie;
2861 pthread_mutex_unlock(&out->lock);
2862 return 0;
2863}
2864
2865static int out_pause(struct audio_stream_out* stream)
2866{
2867 struct stream_out *out = (struct stream_out *)stream;
2868 int status = -ENOSYS;
2869 ALOGV("%s", __func__);
2870 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002871 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2873 status = compress_pause(out->compr);
2874 out->offload_state = OFFLOAD_STATE_PAUSED;
2875 }
2876 pthread_mutex_unlock(&out->lock);
2877 }
2878 return status;
2879}
2880
2881static int out_resume(struct audio_stream_out* stream)
2882{
2883 struct stream_out *out = (struct stream_out *)stream;
2884 int status = -ENOSYS;
2885 ALOGV("%s", __func__);
2886 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2887 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002888 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2890 status = compress_resume(out->compr);
2891 out->offload_state = OFFLOAD_STATE_PLAYING;
2892 }
2893 pthread_mutex_unlock(&out->lock);
2894 }
2895 return status;
2896}
2897
2898static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2899{
2900 struct stream_out *out = (struct stream_out *)stream;
2901 int status = -ENOSYS;
2902 ALOGV("%s", __func__);
2903 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002904 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002905 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2906 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2907 else
2908 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2909 pthread_mutex_unlock(&out->lock);
2910 }
2911 return status;
2912}
2913
2914static int out_flush(struct audio_stream_out* stream)
2915{
2916 struct stream_out *out = (struct stream_out *)stream;
2917 ALOGV("%s", __func__);
2918 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002919 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002920 stop_compressed_output_l(out);
2921 pthread_mutex_unlock(&out->lock);
2922 return 0;
2923 }
2924 return -ENOSYS;
2925}
2926
Eric Laurent0e46adf2016-12-16 12:49:24 -08002927static int out_stop(const struct audio_stream_out* stream)
2928{
2929 struct stream_out *out = (struct stream_out *)stream;
2930 struct audio_device *adev = out->dev;
2931 int ret = -ENOSYS;
2932
2933 ALOGV("%s", __func__);
2934 pthread_mutex_lock(&adev->lock);
2935 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2936 out->playback_started && out->pcm != NULL) {
2937 pcm_stop(out->pcm);
2938 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002939 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002940 }
2941 pthread_mutex_unlock(&adev->lock);
2942 return ret;
2943}
2944
2945static int out_start(const struct audio_stream_out* stream)
2946{
2947 struct stream_out *out = (struct stream_out *)stream;
2948 struct audio_device *adev = out->dev;
2949 int ret = -ENOSYS;
2950
2951 ALOGV("%s", __func__);
2952 pthread_mutex_lock(&adev->lock);
2953 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2954 !out->playback_started && out->pcm != NULL) {
2955 ret = start_output_stream(out);
2956 if (ret == 0) {
2957 out->playback_started = true;
2958 }
2959 }
2960 pthread_mutex_unlock(&adev->lock);
2961 return ret;
2962}
2963
Phil Burkbc991042017-02-24 08:06:44 -08002964/*
2965 * Modify config->period_count based on min_size_frames
2966 */
2967static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2968{
2969 int periodCountRequested = (min_size_frames + config->period_size - 1)
2970 / config->period_size;
2971 int periodCount = MMAP_PERIOD_COUNT_MIN;
2972
2973 ALOGV("%s original config.period_size = %d config.period_count = %d",
2974 __func__, config->period_size, config->period_count);
2975
2976 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2977 periodCount *= 2;
2978 }
2979 config->period_count = periodCount;
2980
2981 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2982}
2983
Eric Laurent0e46adf2016-12-16 12:49:24 -08002984static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2985 int32_t min_size_frames,
2986 struct audio_mmap_buffer_info *info)
2987{
2988 struct stream_out *out = (struct stream_out *)stream;
2989 struct audio_device *adev = out->dev;
2990 int ret = 0;
2991 unsigned int offset1;
2992 unsigned int frames1;
2993 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002994 uint32_t mmap_size;
2995 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002996
2997 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08002998 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002999 pthread_mutex_lock(&adev->lock);
3000
3001 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003002 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003003 ret = -EINVAL;
3004 goto exit;
3005 }
3006 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003007 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003008 ret = -ENOSYS;
3009 goto exit;
3010 }
3011 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3012 if (out->pcm_device_id < 0) {
3013 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3014 __func__, out->pcm_device_id, out->usecase);
3015 ret = -EINVAL;
3016 goto exit;
3017 }
Phil Burkbc991042017-02-24 08:06:44 -08003018
3019 adjust_mmap_period_count(&out->config, min_size_frames);
3020
Eric Laurent0e46adf2016-12-16 12:49:24 -08003021 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3022 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3023 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3024 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3025 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3026 step = "open";
3027 ret = -ENODEV;
3028 goto exit;
3029 }
3030 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3031 if (ret < 0) {
3032 step = "begin";
3033 goto exit;
3034 }
3035 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003036 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003037 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003038 ret = platform_get_mmap_data_fd(adev->platform,
3039 out->pcm_device_id, 0 /*playback*/,
3040 &info->shared_memory_fd,
3041 &mmap_size);
3042 if (ret < 0) {
3043 // Fall back to non exclusive mode
3044 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3045 } else {
3046 if (mmap_size < buffer_size) {
3047 step = "mmap";
3048 goto exit;
3049 }
3050 // FIXME: indicate exclusive mode support by returning a negative buffer size
3051 info->buffer_size_frames *= -1;
3052 }
3053 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003054
3055 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3056 if (ret < 0) {
3057 step = "commit";
3058 goto exit;
3059 }
Phil Burkbc991042017-02-24 08:06:44 -08003060
3061 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003062 ret = 0;
3063
3064 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3065 __func__, info->shared_memory_address, info->buffer_size_frames);
3066
3067exit:
3068 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003069 if (out->pcm == NULL) {
3070 ALOGE("%s: %s - %d", __func__, step, ret);
3071 } else {
3072 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003073 pcm_close(out->pcm);
3074 out->pcm = NULL;
3075 }
3076 }
3077 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003078 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003079 return ret;
3080}
3081
3082static int out_get_mmap_position(const struct audio_stream_out *stream,
3083 struct audio_mmap_position *position)
3084{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003085 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003086 struct stream_out *out = (struct stream_out *)stream;
3087 ALOGVV("%s", __func__);
3088 if (position == NULL) {
3089 return -EINVAL;
3090 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003091 lock_output_stream(out);
3092 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3093 out->pcm == NULL) {
3094 ret = -ENOSYS;
3095 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003096 }
3097
3098 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003099 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003100 if (ret < 0) {
3101 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003102 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003103 }
Andy Hungfc044e12017-03-20 09:24:22 -07003104 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003105exit:
3106 pthread_mutex_unlock(&out->lock);
3107 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003108}
3109
3110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003111/** audio_stream_in implementation **/
3112static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3113{
3114 struct stream_in *in = (struct stream_in *)stream;
3115
3116 return in->config.rate;
3117}
3118
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003119static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003120{
3121 return -ENOSYS;
3122}
3123
3124static size_t in_get_buffer_size(const struct audio_stream *stream)
3125{
3126 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003127 return in->config.period_size * in->af_period_multiplier *
3128 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003129}
3130
3131static uint32_t in_get_channels(const struct audio_stream *stream)
3132{
3133 struct stream_in *in = (struct stream_in *)stream;
3134
3135 return in->channel_mask;
3136}
3137
vivek mehta4ed66e62016-04-15 23:33:34 -07003138static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139{
vivek mehta4ed66e62016-04-15 23:33:34 -07003140 struct stream_in *in = (struct stream_in *)stream;
3141 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142}
3143
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003144static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145{
3146 return -ENOSYS;
3147}
3148
3149static int in_standby(struct audio_stream *stream)
3150{
3151 struct stream_in *in = (struct stream_in *)stream;
3152 struct audio_device *adev = in->dev;
3153 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003154 bool do_stop = true;
3155
Eric Laurent994a6932013-07-17 11:51:42 -07003156 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003157
3158 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003159
3160 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003161 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003162 audio_extn_sound_trigger_stop_lab(in);
3163 in->standby = true;
3164 }
3165
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003167 if (adev->adm_deregister_stream)
3168 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3169
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003170 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003172 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003173 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003174 in->capture_started = false;
3175 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003176 if (in->pcm) {
3177 pcm_close(in->pcm);
3178 in->pcm = NULL;
3179 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003180 adev->enable_voicerx = false;
3181 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003182 if (do_stop) {
3183 status = stop_input_stream(in);
3184 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003185 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 }
3187 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003188 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 return status;
3190}
3191
Andy Hungd13f0d32017-06-12 13:58:37 -07003192static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193{
Andy Hungd13f0d32017-06-12 13:58:37 -07003194 struct stream_in *in = (struct stream_in *)stream;
3195
3196 // We try to get the lock for consistency,
3197 // but it isn't necessary for these variables.
3198 // If we're not in standby, we may be blocked on a read.
3199 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3200 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3201 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3202 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3203
3204 if (locked) {
3205 pthread_mutex_unlock(&in->lock);
3206 }
3207
3208 // dump error info
3209 (void)error_log_dump(
3210 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003211 return 0;
3212}
3213
3214static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3215{
3216 struct stream_in *in = (struct stream_in *)stream;
3217 struct audio_device *adev = in->dev;
3218 struct str_parms *parms;
3219 char *str;
3220 char value[32];
3221 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003222 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223
Eric Laurent994a6932013-07-17 11:51:42 -07003224 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003225 parms = str_parms_create_str(kvpairs);
3226
3227 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3228
Eric Laurenta1478072015-09-21 17:21:52 -07003229 lock_input_stream(in);
3230
Eric Laurent150dbfe2013-02-27 14:31:02 -08003231 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 if (ret >= 0) {
3233 val = atoi(value);
3234 /* no audio source uses val == 0 */
3235 if ((in->source != val) && (val != 0)) {
3236 in->source = val;
3237 }
3238 }
3239
3240 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242 if (ret >= 0) {
3243 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003244 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003245
3246 // Workaround: If routing to an non existing usb device, fail gracefully
3247 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003248 int card;
3249 if (audio_is_usb_in_device(val) &&
3250 (card = get_alive_usb_card(parms)) >= 0) {
3251
3252 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003253 status = -ENOSYS;
3254 } else {
3255
3256 in->device = val;
3257 /* If recording is in progress, change the tx device to new device */
3258 if (!in->standby) {
3259 ALOGV("update input routing change");
3260 // inform adm before actual routing to prevent glitches.
3261 if (adev->adm_on_routing_change) {
3262 adev->adm_on_routing_change(adev->adm_data,
3263 in->capture_handle);
3264 }
3265 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003266 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003267 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268 }
3269 }
3270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003272 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273
3274 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003275 ALOGV("%s: exit: status(%d)", __func__, status);
3276 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003277}
3278
Haynes Mathew George569b7482017-05-08 14:44:27 -07003279static char* in_get_parameters(const struct audio_stream *stream,
3280 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003281{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003282 struct stream_in *in = (struct stream_in *)stream;
3283 struct str_parms *query = str_parms_create_str(keys);
3284 char *str;
3285 struct str_parms *reply = str_parms_create();
3286 bool replied = false;
3287
3288 ALOGV("%s: enter: keys - %s", __func__, keys);
3289 replied |= stream_get_parameter_channels(query, reply,
3290 &in->supported_channel_masks[0]);
3291 replied |= stream_get_parameter_formats(query, reply,
3292 &in->supported_formats[0]);
3293 replied |= stream_get_parameter_rates(query, reply,
3294 &in->supported_sample_rates[0]);
3295 if (replied) {
3296 str = str_parms_to_str(reply);
3297 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003298 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003299 }
3300 str_parms_destroy(query);
3301 str_parms_destroy(reply);
3302 ALOGV("%s: exit: returns - %s", __func__, str);
3303 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304}
3305
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003306static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003308 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309}
3310
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003311static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3312{
3313 if (!stream || !parms)
3314 return;
3315
3316 struct stream_in *in = (struct stream_in *)stream;
3317 struct audio_device *adev = in->dev;
3318
3319 card_status_t status;
3320 int card;
3321 if (parse_snd_card_status(parms, &card, &status) < 0)
3322 return;
3323
3324 pthread_mutex_lock(&adev->lock);
3325 bool valid_cb = (card == adev->snd_card);
3326 pthread_mutex_unlock(&adev->lock);
3327
3328 if (!valid_cb)
3329 return;
3330
3331 lock_input_stream(in);
3332 if (in->card_status != status)
3333 in->card_status = status;
3334 pthread_mutex_unlock(&in->lock);
3335
3336 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3337 use_case_table[in->usecase],
3338 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3339
3340 // a better solution would be to report error back to AF and let
3341 // it put the stream to standby
3342 if (status == CARD_STATUS_OFFLINE)
3343 in_standby(&in->stream.common);
3344
3345 return;
3346}
3347
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3349 size_t bytes)
3350{
3351 struct stream_in *in = (struct stream_in *)stream;
3352 struct audio_device *adev = in->dev;
3353 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003354 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003355 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356
Eric Laurenta1478072015-09-21 17:21:52 -07003357 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003358 const size_t frame_size = audio_stream_in_frame_size(stream);
3359 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003360
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003361 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003362 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003363 /* Read from sound trigger HAL */
3364 audio_extn_sound_trigger_read(in, buffer, bytes);
3365 pthread_mutex_unlock(&in->lock);
3366 return bytes;
3367 }
3368
Eric Laurent0e46adf2016-12-16 12:49:24 -08003369 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3370 ret = -ENOSYS;
3371 goto exit;
3372 }
3373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003375 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003377 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003378 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 goto exit;
3380 }
3381 in->standby = 0;
3382 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383
Andy Hungd13f0d32017-06-12 13:58:37 -07003384 // errors that occur here are read errors.
3385 error_code = ERROR_CODE_READ;
3386
Haynes Mathew George03c40102016-01-29 17:57:48 -08003387 //what's the duration requested by the client?
3388 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3389 in->config.rate;
3390 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003391
Haynes Mathew George03c40102016-01-29 17:57:48 -08003392 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003394 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003395 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003396 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003397 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003398 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003399 if (ret < 0) {
3400 ALOGE("Failed to read w/err %s", strerror(errno));
3401 ret = -errno;
3402 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003403 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3404 if (bytes % 4 == 0) {
3405 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3406 int_buf_stream = buffer;
3407 for (size_t itt=0; itt < bytes/4 ; itt++) {
3408 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003409 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003410 } else {
3411 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3412 ret = -EINVAL;
3413 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003414 }
3415 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 }
3417
Haynes Mathew George03c40102016-01-29 17:57:48 -08003418 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420 /*
3421 * Instead of writing zeroes here, we could trust the hardware
3422 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003423 * 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 -08003424 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003425 if (ret == 0 && adev->mic_muted &&
3426 !voice_is_in_call_rec_stream(in) &&
3427 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003429 in->frames_muted += frames;
3430 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431
3432exit:
3433 pthread_mutex_unlock(&in->lock);
3434
3435 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003436 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003437 in_standby(&in->stream.common);
3438 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003439 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003440 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003441 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003442 }
3443 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003444 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003445 }
3446 return bytes;
3447}
3448
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003449static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450{
3451 return 0;
3452}
3453
Andy Hung6ebe5962016-01-15 17:46:57 -08003454static int in_get_capture_position(const struct audio_stream_in *stream,
3455 int64_t *frames, int64_t *time)
3456{
3457 if (stream == NULL || frames == NULL || time == NULL) {
3458 return -EINVAL;
3459 }
3460 struct stream_in *in = (struct stream_in *)stream;
3461 int ret = -ENOSYS;
3462
3463 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003464 // note: ST sessions do not close the alsa pcm driver synchronously
3465 // on standby. Therefore, we may return an error even though the
3466 // pcm stream is still opened.
3467 if (in->standby) {
3468 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3469 "%s stream in standby but pcm not NULL for non ST session", __func__);
3470 goto exit;
3471 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003472 if (in->pcm) {
3473 struct timespec timestamp;
3474 unsigned int avail;
3475 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3476 *frames = in->frames_read + avail;
3477 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3478 ret = 0;
3479 }
3480 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003481exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003482 pthread_mutex_unlock(&in->lock);
3483 return ret;
3484}
3485
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003486static int add_remove_audio_effect(const struct audio_stream *stream,
3487 effect_handle_t effect,
3488 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003490 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003491 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003492 int status = 0;
3493 effect_descriptor_t desc;
3494
3495 status = (*effect)->get_descriptor(effect, &desc);
3496 if (status != 0)
3497 return status;
3498
Eric Laurenta1478072015-09-21 17:21:52 -07003499 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003500 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003501 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003502 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003503 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003504 in->enable_aec != enable &&
3505 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3506 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003507 if (!enable)
3508 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003509 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3510 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3511 adev->enable_voicerx = enable;
3512 struct audio_usecase *usecase;
3513 struct listnode *node;
3514 list_for_each(node, &adev->usecase_list) {
3515 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003516 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003517 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003518 }
3519 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003520 if (!in->standby)
3521 select_devices(in->dev, in->usecase);
3522 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003523 if (in->enable_ns != enable &&
3524 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3525 in->enable_ns = enable;
3526 if (!in->standby)
3527 select_devices(in->dev, in->usecase);
3528 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003529 pthread_mutex_unlock(&in->dev->lock);
3530 pthread_mutex_unlock(&in->lock);
3531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532 return 0;
3533}
3534
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003535static int in_add_audio_effect(const struct audio_stream *stream,
3536 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003537{
Eric Laurent994a6932013-07-17 11:51:42 -07003538 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003539 return add_remove_audio_effect(stream, effect, true);
3540}
3541
3542static int in_remove_audio_effect(const struct audio_stream *stream,
3543 effect_handle_t effect)
3544{
Eric Laurent994a6932013-07-17 11:51:42 -07003545 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003546 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547}
3548
Eric Laurent0e46adf2016-12-16 12:49:24 -08003549static int in_stop(const struct audio_stream_in* stream)
3550{
3551 struct stream_in *in = (struct stream_in *)stream;
3552 struct audio_device *adev = in->dev;
3553
3554 int ret = -ENOSYS;
3555 ALOGV("%s", __func__);
3556 pthread_mutex_lock(&adev->lock);
3557 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3558 in->capture_started && in->pcm != NULL) {
3559 pcm_stop(in->pcm);
3560 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003561 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003562 }
3563 pthread_mutex_unlock(&adev->lock);
3564 return ret;
3565}
3566
3567static int in_start(const struct audio_stream_in* stream)
3568{
3569 struct stream_in *in = (struct stream_in *)stream;
3570 struct audio_device *adev = in->dev;
3571 int ret = -ENOSYS;
3572
3573 ALOGV("%s in %p", __func__, in);
3574 pthread_mutex_lock(&adev->lock);
3575 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3576 !in->capture_started && in->pcm != NULL) {
3577 if (!in->capture_started) {
3578 ret = start_input_stream(in);
3579 if (ret == 0) {
3580 in->capture_started = true;
3581 }
3582 }
3583 }
3584 pthread_mutex_unlock(&adev->lock);
3585 return ret;
3586}
3587
3588static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3589 int32_t min_size_frames,
3590 struct audio_mmap_buffer_info *info)
3591{
3592 struct stream_in *in = (struct stream_in *)stream;
3593 struct audio_device *adev = in->dev;
3594 int ret = 0;
3595 unsigned int offset1;
3596 unsigned int frames1;
3597 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003598 uint32_t mmap_size;
3599 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003600
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003601 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003602 pthread_mutex_lock(&adev->lock);
3603 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003604
Eric Laurent0e46adf2016-12-16 12:49:24 -08003605 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003606 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003607 ret = -EINVAL;
3608 goto exit;
3609 }
3610 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003611 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003612 ALOGV("%s in %p", __func__, in);
3613 ret = -ENOSYS;
3614 goto exit;
3615 }
3616 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3617 if (in->pcm_device_id < 0) {
3618 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3619 __func__, in->pcm_device_id, in->usecase);
3620 ret = -EINVAL;
3621 goto exit;
3622 }
Phil Burkbc991042017-02-24 08:06:44 -08003623
3624 adjust_mmap_period_count(&in->config, min_size_frames);
3625
Eric Laurent0e46adf2016-12-16 12:49:24 -08003626 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3627 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3628 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3629 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3630 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3631 step = "open";
3632 ret = -ENODEV;
3633 goto exit;
3634 }
3635
3636 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3637 if (ret < 0) {
3638 step = "begin";
3639 goto exit;
3640 }
3641 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003642 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003643 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003644 ret = platform_get_mmap_data_fd(adev->platform,
3645 in->pcm_device_id, 1 /*capture*/,
3646 &info->shared_memory_fd,
3647 &mmap_size);
3648 if (ret < 0) {
3649 // Fall back to non exclusive mode
3650 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3651 } else {
3652 if (mmap_size < buffer_size) {
3653 step = "mmap";
3654 goto exit;
3655 }
3656 // FIXME: indicate exclusive mode support by returning a negative buffer size
3657 info->buffer_size_frames *= -1;
3658 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003659
Haynes Mathew George96483a22017-03-28 14:52:47 -07003660 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003661
3662 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3663 if (ret < 0) {
3664 step = "commit";
3665 goto exit;
3666 }
3667
Phil Burkbc991042017-02-24 08:06:44 -08003668 in->standby = false;
3669 ret = 0;
3670
Eric Laurent0e46adf2016-12-16 12:49:24 -08003671 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3672 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003673
3674exit:
3675 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003676 if (in->pcm == NULL) {
3677 ALOGE("%s: %s - %d", __func__, step, ret);
3678 } else {
3679 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003680 pcm_close(in->pcm);
3681 in->pcm = NULL;
3682 }
3683 }
3684 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003685 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003686 return ret;
3687}
3688
3689static int in_get_mmap_position(const struct audio_stream_in *stream,
3690 struct audio_mmap_position *position)
3691{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003692 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003693 struct stream_in *in = (struct stream_in *)stream;
3694 ALOGVV("%s", __func__);
3695 if (position == NULL) {
3696 return -EINVAL;
3697 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003698 lock_input_stream(in);
3699 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3700 in->pcm == NULL) {
3701 ret = -ENOSYS;
3702 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003703 }
3704 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003705 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003706 if (ret < 0) {
3707 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003708 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003709 }
Andy Hungfc044e12017-03-20 09:24:22 -07003710 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003711exit:
3712 pthread_mutex_unlock(&in->lock);
3713 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003714}
3715
3716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003717static int adev_open_output_stream(struct audio_hw_device *dev,
3718 audio_io_handle_t handle,
3719 audio_devices_t devices,
3720 audio_output_flags_t flags,
3721 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003722 struct audio_stream_out **stream_out,
3723 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724{
3725 struct audio_device *adev = (struct audio_device *)dev;
3726 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003727 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003728 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3729 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3730 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731
Andy Hungd9653bd2017-08-01 19:31:39 -07003732 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3733 return -ENOSYS;
3734 }
3735
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003736 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3737 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 *stream_out = NULL;
3739 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3740
3741 if (devices == AUDIO_DEVICE_NONE)
3742 devices = AUDIO_DEVICE_OUT_SPEAKER;
3743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003744 out->flags = flags;
3745 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003746 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003747 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003748 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003749
3750 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003751 if ((is_hdmi || is_usb_dev) &&
3752 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3753 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3754 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003755 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003756 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003757 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003758 if (config->sample_rate == 0)
3759 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3760 if (config->channel_mask == 0)
3761 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3762 if (config->format == AUDIO_FORMAT_DEFAULT)
3763 config->format = AUDIO_FORMAT_PCM_16_BIT;
3764 } else if (is_usb_dev) {
3765 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3766 &config->format,
3767 &out->supported_formats[0],
3768 MAX_SUPPORTED_FORMATS,
3769 &config->channel_mask,
3770 &out->supported_channel_masks[0],
3771 MAX_SUPPORTED_CHANNEL_MASKS,
3772 &config->sample_rate,
3773 &out->supported_sample_rates[0],
3774 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003775 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003776 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003777 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003778 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003779 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003780
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003781
Haynes Mathew George569b7482017-05-08 14:44:27 -07003782 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003783 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003784 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003785 if (is_hdmi) {
3786 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3787 out->config = pcm_config_hdmi_multi;
3788 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3789 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3790 out->config = pcm_config_mmap_playback;
3791 out->stream.start = out_start;
3792 out->stream.stop = out_stop;
3793 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3794 out->stream.get_mmap_position = out_get_mmap_position;
3795 } else {
3796 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3797 out->config = pcm_config_hifi;
3798 }
3799
3800 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003801 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003802 if (is_hdmi) {
3803 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3804 audio_bytes_per_sample(out->format));
3805 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003806 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003807 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003808 pthread_mutex_lock(&adev->lock);
3809 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3810 pthread_mutex_unlock(&adev->lock);
3811
3812 // reject offload during card offline to allow
3813 // fallback to s/w paths
3814 if (offline) {
3815 ret = -ENODEV;
3816 goto error_open;
3817 }
3818
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003819 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3820 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3821 ALOGE("%s: Unsupported Offload information", __func__);
3822 ret = -EINVAL;
3823 goto error_open;
3824 }
3825 if (!is_supported_format(config->offload_info.format)) {
3826 ALOGE("%s: Unsupported audio format", __func__);
3827 ret = -EINVAL;
3828 goto error_open;
3829 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003830 out->sample_rate = config->offload_info.sample_rate;
3831 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
3832 out->channel_mask = config->offload_info.channel_mask;
3833 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
3834 out->channel_mask = config->channel_mask;
3835 else
3836 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3837
3838 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003839
3840 out->compr_config.codec = (struct snd_codec *)
3841 calloc(1, sizeof(struct snd_codec));
3842
3843 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003844
3845 out->stream.set_callback = out_set_callback;
3846 out->stream.pause = out_pause;
3847 out->stream.resume = out_resume;
3848 out->stream.drain = out_drain;
3849 out->stream.flush = out_flush;
3850
3851 out->compr_config.codec->id =
3852 get_snd_codec_id(config->offload_info.format);
3853 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3854 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003855 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003856 out->compr_config.codec->bit_rate =
3857 config->offload_info.bit_rate;
3858 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003859 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003860 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3861
3862 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3863 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003864
3865 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003866 create_offload_callback_thread(out);
3867 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3868 __func__, config->offload_info.version,
3869 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003870 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3871 switch (config->sample_rate) {
3872 case 0:
3873 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3874 break;
3875 case 8000:
3876 case 16000:
3877 case 48000:
3878 out->sample_rate = config->sample_rate;
3879 break;
3880 default:
3881 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
3882 config->sample_rate);
3883 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3884 ret = -EINVAL;
3885 goto error_open;
3886 }
3887 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3888 switch (config->channel_mask) {
3889 case AUDIO_CHANNEL_NONE:
3890 case AUDIO_CHANNEL_OUT_STEREO:
3891 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3892 break;
3893 default:
3894 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
3895 config->channel_mask);
3896 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3897 ret = -EINVAL;
3898 goto error_open;
3899 }
3900 switch (config->format) {
3901 case AUDIO_FORMAT_DEFAULT:
3902 case AUDIO_FORMAT_PCM_16_BIT:
3903 out->format = AUDIO_FORMAT_PCM_16_BIT;
3904 break;
3905 default:
3906 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
3907 config->format);
3908 config->format = AUDIO_FORMAT_PCM_16_BIT;
3909 ret = -EINVAL;
3910 goto error_open;
3911 }
3912
3913 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003914 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003915 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003916 case 0:
3917 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
3918 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07003919 case 8000:
3920 case 16000:
3921 case 48000:
3922 out->sample_rate = config->sample_rate;
3923 break;
3924 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003925 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
3926 config->sample_rate);
3927 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3928 ret = -EINVAL;
3929 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003930 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003931 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3932 switch (config->channel_mask) {
3933 case AUDIO_CHANNEL_NONE:
3934 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3935 break;
3936 case AUDIO_CHANNEL_OUT_STEREO:
3937 out->channel_mask = config->channel_mask;
3938 break;
3939 default:
3940 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
3941 config->channel_mask);
3942 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3943 ret = -EINVAL;
3944 break;
3945 }
3946 switch (config->format) {
3947 case AUDIO_FORMAT_DEFAULT:
3948 out->format = AUDIO_FORMAT_PCM_16_BIT;
3949 break;
3950 case AUDIO_FORMAT_PCM_16_BIT:
3951 out->format = config->format;
3952 break;
3953 default:
3954 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
3955 config->format);
3956 config->format = AUDIO_FORMAT_PCM_16_BIT;
3957 ret = -EINVAL;
3958 break;
3959 }
3960 if (ret != 0)
3961 goto error_open;
3962
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003963 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3964 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003965 out->config.rate = out->sample_rate;
3966 out->config.channels =
3967 audio_channel_count_from_out_mask(out->channel_mask);
3968 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003969 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003970 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
3971 switch (config->sample_rate) {
3972 case 0:
3973 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3974 break;
3975 case 8000:
3976 case 16000:
3977 case 32000:
3978 case 48000:
3979 out->sample_rate = config->sample_rate;
3980 break;
3981 default:
3982 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
3983 config->sample_rate);
3984 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3985 ret = -EINVAL;
3986 break;
3987 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003988 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003989 switch (config->channel_mask) {
3990 case AUDIO_CHANNEL_NONE:
3991 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3992 break;
3993 case AUDIO_CHANNEL_OUT_STEREO:
3994 out->channel_mask = config->channel_mask;
3995 break;
3996 default:
3997 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
3998 config->channel_mask);
3999 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4000 ret = -EINVAL;
4001 break;
4002 }
4003 switch (config->format) {
4004 case AUDIO_FORMAT_DEFAULT:
4005 out->format = AUDIO_FORMAT_PCM_16_BIT;
4006 break;
4007 case AUDIO_FORMAT_PCM_16_BIT:
4008 out->format = config->format;
4009 break;
4010 default:
4011 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4012 config->format);
4013 config->format = AUDIO_FORMAT_PCM_16_BIT;
4014 ret = -EINVAL;
4015 break;
4016 }
4017 if (ret != 0)
4018 goto error_open;
4019
vivek mehtaa68fea62017-06-08 19:04:02 -07004020 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004021 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4022 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004023 out->config.rate = out->sample_rate;
4024 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004025 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004026 out->sample_rate,
4027 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004028 out->config.channels,
4029 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004030 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004031 out->config.period_size = buffer_size / frame_size;
4032 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4033 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004034 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004035 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004036 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4037 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004038 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004039 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4040 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004041 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004042 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004043 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004044 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004045 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004046 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4047 out->config = pcm_config_mmap_playback;
4048 out->stream.start = out_start;
4049 out->stream.stop = out_stop;
4050 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4051 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004052 } else {
4053 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4054 out->config = pcm_config_low_latency;
4055 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004056
4057 if (config->sample_rate == 0) {
4058 out->sample_rate = out->config.rate;
4059 } else {
4060 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004061 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004062 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4063 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4064 } else {
4065 out->channel_mask = config->channel_mask;
4066 }
4067 if (config->format == AUDIO_FORMAT_DEFAULT)
4068 out->format = audio_format_from_pcm_format(out->config.format);
4069 else if (!audio_is_linear_pcm(config->format)) {
4070 config->format = AUDIO_FORMAT_PCM_16_BIT;
4071 ret = -EINVAL;
4072 goto error_open;
4073 } else {
4074 out->format = config->format;
4075 }
4076
4077 out->config.rate = out->sample_rate;
4078 out->config.channels =
4079 audio_channel_count_from_out_mask(out->channel_mask);
4080 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4081 out->config.format = pcm_format_from_audio_format(out->format);
4082 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004083 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004084
4085 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4086 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004087 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004088 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4089 __func__, config->sample_rate, config->format, config->channel_mask);
4090 config->sample_rate = out->sample_rate;
4091 config->format = out->format;
4092 config->channel_mask = out->channel_mask;
4093 ret = -EINVAL;
4094 goto error_open;
4095 }
4096
Andy Hung6fcba9c2014-03-18 11:53:32 -07004097 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4098 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004100 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004101 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004102 adev->primary_output = out;
4103 else {
4104 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004105 ret = -EEXIST;
4106 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004107 }
4108 }
4109
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004110 /* Check if this usecase is already existing */
4111 pthread_mutex_lock(&adev->lock);
4112 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4113 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004114 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004115 ret = -EEXIST;
4116 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004117 }
4118 pthread_mutex_unlock(&adev->lock);
4119
4120 out->stream.common.get_sample_rate = out_get_sample_rate;
4121 out->stream.common.set_sample_rate = out_set_sample_rate;
4122 out->stream.common.get_buffer_size = out_get_buffer_size;
4123 out->stream.common.get_channels = out_get_channels;
4124 out->stream.common.get_format = out_get_format;
4125 out->stream.common.set_format = out_set_format;
4126 out->stream.common.standby = out_standby;
4127 out->stream.common.dump = out_dump;
4128 out->stream.common.set_parameters = out_set_parameters;
4129 out->stream.common.get_parameters = out_get_parameters;
4130 out->stream.common.add_audio_effect = out_add_audio_effect;
4131 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4132 out->stream.get_latency = out_get_latency;
4133 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004134#ifdef NO_AUDIO_OUT
4135 out->stream.write = out_write_for_no_output;
4136#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004138#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139 out->stream.get_render_position = out_get_render_position;
4140 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004141 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142
Eric Laurent0e46adf2016-12-16 12:49:24 -08004143 if (out->realtime)
4144 out->af_period_multiplier = af_period_multiplier;
4145 else
4146 out->af_period_multiplier = 1;
4147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004148 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004149 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004150 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004151
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004152 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004153 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004154 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4155
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156 config->format = out->stream.common.get_format(&out->stream.common);
4157 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4158 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4159
Andy Hunga452b0a2017-03-15 14:51:15 -07004160 out->error_log = error_log_create(
4161 ERROR_LOG_ENTRIES,
4162 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4163
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004164 /*
4165 By locking output stream before registering, we allow the callback
4166 to update stream's state only after stream's initial state is set to
4167 adev state.
4168 */
4169 lock_output_stream(out);
4170 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4171 pthread_mutex_lock(&adev->lock);
4172 out->card_status = adev->card_status;
4173 pthread_mutex_unlock(&adev->lock);
4174 pthread_mutex_unlock(&out->lock);
4175
vivek mehta4a824772017-06-08 19:05:49 -07004176 stream_app_type_cfg_init(&out->app_type_cfg);
4177
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004178 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004179
Eric Laurent994a6932013-07-17 11:51:42 -07004180 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004181 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004182
4183error_open:
4184 free(out);
4185 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004186 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004187 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004188}
4189
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004190static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191 struct audio_stream_out *stream)
4192{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004193 struct stream_out *out = (struct stream_out *)stream;
4194 struct audio_device *adev = out->dev;
4195
Eric Laurent994a6932013-07-17 11:51:42 -07004196 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004197
4198 // must deregister from sndmonitor first to prevent races
4199 // between the callback and close_stream
4200 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004202 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4203 destroy_offload_callback_thread(out);
4204
4205 if (out->compr_config.codec != NULL)
4206 free(out->compr_config.codec);
4207 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004208
4209 if (adev->voice_tx_output == out)
4210 adev->voice_tx_output = NULL;
4211
Andy Hunga452b0a2017-03-15 14:51:15 -07004212 error_log_destroy(out->error_log);
4213 out->error_log = NULL;
4214
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004215 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004216 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004217 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004219 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220}
4221
4222static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4223{
4224 struct audio_device *adev = (struct audio_device *)dev;
4225 struct str_parms *parms;
4226 char *str;
4227 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004228 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004229 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004230 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231
Joe Onorato188b6222016-03-01 11:02:27 -08004232 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004233
4234 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004235
4236 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004237 status = voice_set_parameters(adev, parms);
4238 if (status != 0) {
4239 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004240 }
4241
4242 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4243 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004244 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4246 adev->bluetooth_nrec = true;
4247 else
4248 adev->bluetooth_nrec = false;
4249 }
4250
4251 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4252 if (ret >= 0) {
4253 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4254 adev->screen_off = false;
4255 else
4256 adev->screen_off = true;
4257 }
4258
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004259 ret = str_parms_get_int(parms, "rotation", &val);
4260 if (ret >= 0) {
4261 bool reverse_speakers = false;
4262 switch(val) {
4263 // FIXME: note that the code below assumes that the speakers are in the correct placement
4264 // relative to the user when the device is rotated 90deg from its default rotation. This
4265 // assumption is device-specific, not platform-specific like this code.
4266 case 270:
4267 reverse_speakers = true;
4268 break;
4269 case 0:
4270 case 90:
4271 case 180:
4272 break;
4273 default:
4274 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004275 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004276 }
Eric Laurent03f09432014-03-25 18:09:11 -07004277 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004278 // check and set swap
4279 // - check if orientation changed and speaker active
4280 // - set rotation and cache the rotation value
4281 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004282 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004283 }
4284
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004285 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4286 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004287 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004288 }
4289
David Linee3fe402017-03-13 10:00:42 -07004290 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4291 if (ret >= 0) {
4292 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004293 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004294 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4295 if (ret >= 0) {
4296 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004297 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004298 }
Eric Laurent99dab492017-06-17 15:19:08 -07004299 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004300 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4301 if (ret >= 0) {
4302 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004303 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004304 }
4305 }
4306 }
4307
4308 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4309 if (ret >= 0) {
4310 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004311 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004312 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4313 if (ret >= 0) {
4314 const int card = atoi(value);
4315
Eric Laurent99dab492017-06-17 15:19:08 -07004316 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004317 }
Eric Laurent99dab492017-06-17 15:19:08 -07004318 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004319 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4320 if (ret >= 0) {
4321 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004322 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004323 }
4324 }
4325 }
4326
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004327 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004328done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004329 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004330 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004331 ALOGV("%s: exit with code(%d)", __func__, status);
4332 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004333}
4334
4335static char* adev_get_parameters(const struct audio_hw_device *dev,
4336 const char *keys)
4337{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004338 struct audio_device *adev = (struct audio_device *)dev;
4339 struct str_parms *reply = str_parms_create();
4340 struct str_parms *query = str_parms_create_str(keys);
4341 char *str;
4342
4343 pthread_mutex_lock(&adev->lock);
4344
4345 voice_get_parameters(adev, query, reply);
4346 str = str_parms_to_str(reply);
4347 str_parms_destroy(query);
4348 str_parms_destroy(reply);
4349
4350 pthread_mutex_unlock(&adev->lock);
4351 ALOGV("%s: exit: returns - %s", __func__, str);
4352 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353}
4354
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004355static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356{
4357 return 0;
4358}
4359
Haynes Mathew George5191a852013-09-11 14:19:36 -07004360static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4361{
4362 int ret;
4363 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004364
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004365 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4366
Haynes Mathew George5191a852013-09-11 14:19:36 -07004367 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004368 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004369 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004370
Haynes Mathew George5191a852013-09-11 14:19:36 -07004371 return ret;
4372}
4373
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004374static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375{
4376 return -ENOSYS;
4377}
4378
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004379static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4380 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381{
4382 return -ENOSYS;
4383}
4384
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004385static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004386{
4387 return -ENOSYS;
4388}
4389
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004390static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004391{
4392 return -ENOSYS;
4393}
4394
4395static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4396{
4397 struct audio_device *adev = (struct audio_device *)dev;
4398
4399 pthread_mutex_lock(&adev->lock);
4400 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004401 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004403 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4404 voice_is_in_call(adev)) {
4405 voice_stop_call(adev);
4406 adev->current_call_output = NULL;
4407 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004408 }
4409 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004410
4411 audio_extn_extspk_set_mode(adev->extspk, mode);
4412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413 return 0;
4414}
4415
4416static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4417{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004418 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004419 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420
Eric Laurent2bafff12016-03-17 12:17:23 -07004421 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004422 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004423 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4424 ret = audio_extn_hfp_set_mic_mute(adev, state);
4425 } else {
4426 ret = voice_set_mic_mute(adev, state);
4427 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004428 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004429 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004430
4431 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004432}
4433
4434static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4435{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004436 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437 return 0;
4438}
4439
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004440static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004441 const struct audio_config *config)
4442{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004443 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004444
Eric Laurent74b55762017-07-09 17:04:53 -07004445 /* Don't know if USB HIFI in this context so use true to be conservative */
4446 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4447 true /*is_usb_hifi */) != 0)
4448 return 0;
4449
vivek mehtaa68fea62017-06-08 19:04:02 -07004450 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4451 config->sample_rate, config->format,
4452 channel_count,
4453 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454}
4455
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004456static bool adev_input_allow_hifi_record(struct audio_device *adev,
4457 audio_devices_t devices,
4458 audio_input_flags_t flags,
4459 audio_source_t source) {
4460 const bool allowed = true;
4461
4462 if (!audio_is_usb_in_device(devices))
4463 return !allowed;
4464
4465 switch (flags) {
4466 case AUDIO_INPUT_FLAG_NONE:
4467 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4468 break;
4469 default:
4470 return !allowed;
4471 }
4472
4473 switch (source) {
4474 case AUDIO_SOURCE_DEFAULT:
4475 case AUDIO_SOURCE_MIC:
4476 case AUDIO_SOURCE_UNPROCESSED:
4477 break;
4478 default:
4479 return !allowed;
4480 }
4481
4482 switch (adev->mode) {
4483 case 0:
4484 break;
4485 default:
4486 return !allowed;
4487 }
4488
4489 return allowed;
4490}
4491
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004493 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004494 audio_devices_t devices,
4495 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004496 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004497 audio_input_flags_t flags,
4498 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004499 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500{
4501 struct audio_device *adev = (struct audio_device *)dev;
4502 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004503 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004504 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004505 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004506 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004507 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4508 devices,
4509 flags,
4510 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004511 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004513
Andy Hungd9653bd2017-08-01 19:31:39 -07004514 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4515 return -ENOSYS;
4516 }
4517
Eric Laurent74b55762017-07-09 17:04:53 -07004518 if (!(is_usb_dev && may_use_hifi_record)) {
4519 if (config->sample_rate == 0)
4520 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4521 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4522 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4523 if (config->format == AUDIO_FORMAT_DEFAULT)
4524 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004525
Eric Laurent74b55762017-07-09 17:04:53 -07004526 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4527
4528 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4529 return -EINVAL;
4530 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004531
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004532 if (audio_extn_tfa_98xx_is_supported() &&
4533 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004534 return -EINVAL;
4535
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004536 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4537
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004538 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004539 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004541 in->stream.common.get_sample_rate = in_get_sample_rate;
4542 in->stream.common.set_sample_rate = in_set_sample_rate;
4543 in->stream.common.get_buffer_size = in_get_buffer_size;
4544 in->stream.common.get_channels = in_get_channels;
4545 in->stream.common.get_format = in_get_format;
4546 in->stream.common.set_format = in_set_format;
4547 in->stream.common.standby = in_standby;
4548 in->stream.common.dump = in_dump;
4549 in->stream.common.set_parameters = in_set_parameters;
4550 in->stream.common.get_parameters = in_get_parameters;
4551 in->stream.common.add_audio_effect = in_add_audio_effect;
4552 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4553 in->stream.set_gain = in_set_gain;
4554 in->stream.read = in_read;
4555 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004556 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557
4558 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004559 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004562 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004563 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004564
Haynes Mathew George569b7482017-05-08 14:44:27 -07004565 if (is_usb_dev && may_use_hifi_record) {
4566 /* HiFi record selects an appropriate format, channel, rate combo
4567 depending on sink capabilities*/
4568 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4569 &config->format,
4570 &in->supported_formats[0],
4571 MAX_SUPPORTED_FORMATS,
4572 &config->channel_mask,
4573 &in->supported_channel_masks[0],
4574 MAX_SUPPORTED_CHANNEL_MASKS,
4575 &config->sample_rate,
4576 &in->supported_sample_rates[0],
4577 MAX_SUPPORTED_SAMPLE_RATES);
4578 if (ret != 0) {
4579 ret = -EINVAL;
4580 goto err_open;
4581 }
Eric Laurent74b55762017-07-09 17:04:53 -07004582 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004583 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004584 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004585 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4586 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4587 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4588 bool ret_error = false;
4589 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4590 from HAL is 8_24
4591 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4592 8_24 return error indicating supported format is 8_24
4593 *> In case of any other source requesting 24 bit or float return error
4594 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004595
vivek mehta57ff9b52016-04-28 14:13:08 -07004596 on error flinger will retry with supported format passed
4597 */
4598 if (source != AUDIO_SOURCE_UNPROCESSED) {
4599 config->format = AUDIO_FORMAT_PCM_16_BIT;
4600 ret_error = true;
4601 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4602 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4603 ret_error = true;
4604 }
4605
4606 if (ret_error) {
4607 ret = -EINVAL;
4608 goto err_open;
4609 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004610 }
4611
vivek mehta57ff9b52016-04-28 14:13:08 -07004612 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004613 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004615 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004616 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4617 if (config->sample_rate == 0)
4618 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4619 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4620 config->sample_rate != 8000) {
4621 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4622 ret = -EINVAL;
4623 goto err_open;
4624 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004625
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004626 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4627 config->format = AUDIO_FORMAT_PCM_16_BIT;
4628 ret = -EINVAL;
4629 goto err_open;
4630 }
4631
4632 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4633 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004634 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004635 } else if (is_usb_dev && may_use_hifi_record) {
4636 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4637 in->config = pcm_config_audio_capture;
4638 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004639 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4640 config->sample_rate,
4641 config->format,
4642 channel_count,
4643 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004644 in->config.period_size = buffer_size / frame_size;
4645 in->config.rate = config->sample_rate;
4646 in->af_period_multiplier = 1;
4647 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004648 } else {
4649 in->usecase = USECASE_AUDIO_RECORD;
4650 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004651 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004652 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004653#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004654 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004655#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004656 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004657 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004658 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004659 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004660 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4661 config->sample_rate,
4662 config->format,
4663 channel_count,
4664 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004665 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004666 in->config.rate = config->sample_rate;
4667 in->af_period_multiplier = 1;
4668 } else {
4669 // period size is left untouched for rt mode playback
4670 in->config = pcm_config_audio_capture_rt;
4671 in->af_period_multiplier = af_period_multiplier;
4672 }
4673 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4674 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004675 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004676 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4677 in->config = pcm_config_mmap_capture;
4678 in->stream.start = in_start;
4679 in->stream.stop = in_stop;
4680 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4681 in->stream.get_mmap_position = in_get_mmap_position;
4682 in->af_period_multiplier = 1;
4683 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004684 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004685 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004686 (config->sample_rate == 8000 ||
4687 config->sample_rate == 16000 ||
4688 config->sample_rate == 32000 ||
4689 config->sample_rate == 48000) &&
4690 channel_count == 1) {
4691 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4692 in->config = pcm_config_audio_capture;
4693 frame_size = audio_stream_in_frame_size(&in->stream);
4694 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4695 config->sample_rate,
4696 config->format,
4697 channel_count, false /*is_low_latency*/);
4698 in->config.period_size = buffer_size / frame_size;
4699 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4700 in->config.rate = config->sample_rate;
4701 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004702 } else {
4703 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004704 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004705 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4706 config->sample_rate,
4707 config->format,
4708 channel_count,
4709 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004710 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004711 in->config.rate = config->sample_rate;
4712 in->af_period_multiplier = 1;
4713 }
4714 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4715 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004716 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004718 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004719 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004720
Andy Hungd13f0d32017-06-12 13:58:37 -07004721 in->error_log = error_log_create(
4722 ERROR_LOG_ENTRIES,
4723 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4724
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004725 /* This stream could be for sound trigger lab,
4726 get sound trigger pcm if present */
4727 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004728
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004729 lock_input_stream(in);
4730 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4731 pthread_mutex_lock(&adev->lock);
4732 in->card_status = adev->card_status;
4733 pthread_mutex_unlock(&adev->lock);
4734 pthread_mutex_unlock(&in->lock);
4735
vivek mehta4a824772017-06-08 19:05:49 -07004736 stream_app_type_cfg_init(&in->app_type_cfg);
4737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004738 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004739 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004740 return 0;
4741
4742err_open:
4743 free(in);
4744 *stream_in = NULL;
4745 return ret;
4746}
4747
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004748static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004749 struct audio_stream_in *stream)
4750{
Andy Hungd13f0d32017-06-12 13:58:37 -07004751 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004752 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004753
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004754 // must deregister from sndmonitor first to prevent races
4755 // between the callback and close_stream
4756 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004758
4759 error_log_destroy(in->error_log);
4760 in->error_log = NULL;
4761
Andy Hung0dbb52b2017-08-09 13:51:38 -07004762 pthread_mutex_destroy(&in->pre_lock);
4763 pthread_mutex_destroy(&in->lock);
4764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765 free(stream);
4766
4767 return;
4768}
4769
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004770static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004771{
4772 return 0;
4773}
4774
Andy Hung31aca912014-03-20 17:14:59 -07004775/* verifies input and output devices and their capabilities.
4776 *
4777 * This verification is required when enabling extended bit-depth or
4778 * sampling rates, as not all qcom products support it.
4779 *
4780 * Suitable for calling only on initialization such as adev_open().
4781 * It fills the audio_device use_case_table[] array.
4782 *
4783 * Has a side-effect that it needs to configure audio routing / devices
4784 * in order to power up the devices and read the device parameters.
4785 * It does not acquire any hw device lock. Should restore the devices
4786 * back to "normal state" upon completion.
4787 */
4788static int adev_verify_devices(struct audio_device *adev)
4789{
4790 /* enumeration is a bit difficult because one really wants to pull
4791 * the use_case, device id, etc from the hidden pcm_device_table[].
4792 * In this case there are the following use cases and device ids.
4793 *
4794 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4795 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004796 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004797 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4798 * [USECASE_AUDIO_RECORD] = {0, 0},
4799 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4800 * [USECASE_VOICE_CALL] = {2, 2},
4801 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004802 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004803 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4804 */
4805
4806 /* should be the usecases enabled in adev_open_input_stream() */
4807 static const int test_in_usecases[] = {
4808 USECASE_AUDIO_RECORD,
4809 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4810 };
4811 /* should be the usecases enabled in adev_open_output_stream()*/
4812 static const int test_out_usecases[] = {
4813 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4814 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4815 };
4816 static const usecase_type_t usecase_type_by_dir[] = {
4817 PCM_PLAYBACK,
4818 PCM_CAPTURE,
4819 };
4820 static const unsigned flags_by_dir[] = {
4821 PCM_OUT,
4822 PCM_IN,
4823 };
4824
4825 size_t i;
4826 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004827 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004828 char info[512]; /* for possible debug info */
4829
4830 for (dir = 0; dir < 2; ++dir) {
4831 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4832 const unsigned flags_dir = flags_by_dir[dir];
4833 const size_t testsize =
4834 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4835 const int *testcases =
4836 dir ? test_in_usecases : test_out_usecases;
4837 const audio_devices_t audio_device =
4838 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4839
4840 for (i = 0; i < testsize; ++i) {
4841 const audio_usecase_t audio_usecase = testcases[i];
4842 int device_id;
4843 snd_device_t snd_device;
4844 struct pcm_params **pparams;
4845 struct stream_out out;
4846 struct stream_in in;
4847 struct audio_usecase uc_info;
4848 int retval;
4849
4850 pparams = &adev->use_case_table[audio_usecase];
4851 pcm_params_free(*pparams); /* can accept null input */
4852 *pparams = NULL;
4853
4854 /* find the device ID for the use case (signed, for error) */
4855 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4856 if (device_id < 0)
4857 continue;
4858
4859 /* prepare structures for device probing */
4860 memset(&uc_info, 0, sizeof(uc_info));
4861 uc_info.id = audio_usecase;
4862 uc_info.type = usecase_type;
4863 if (dir) {
4864 adev->active_input = &in;
4865 memset(&in, 0, sizeof(in));
4866 in.device = audio_device;
4867 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4868 uc_info.stream.in = &in;
4869 } else {
4870 adev->active_input = NULL;
4871 }
4872 memset(&out, 0, sizeof(out));
4873 out.devices = audio_device; /* only field needed in select_devices */
4874 uc_info.stream.out = &out;
4875 uc_info.devices = audio_device;
4876 uc_info.in_snd_device = SND_DEVICE_NONE;
4877 uc_info.out_snd_device = SND_DEVICE_NONE;
4878 list_add_tail(&adev->usecase_list, &uc_info.list);
4879
4880 /* select device - similar to start_(in/out)put_stream() */
4881 retval = select_devices(adev, audio_usecase);
4882 if (retval >= 0) {
4883 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4884#if LOG_NDEBUG == 0
4885 if (*pparams) {
4886 ALOGV("%s: (%s) card %d device %d", __func__,
4887 dir ? "input" : "output", card_id, device_id);
4888 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004889 } else {
4890 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4891 }
4892#endif
4893 }
4894
4895 /* deselect device - similar to stop_(in/out)put_stream() */
4896 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004897 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004898 /* 2. Disable the rx device */
4899 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004900 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004901 list_remove(&uc_info.list);
4902 }
4903 }
4904 adev->active_input = NULL; /* restore adev state */
4905 return 0;
4906}
4907
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004908static int adev_close(hw_device_t *device)
4909{
Andy Hung31aca912014-03-20 17:14:59 -07004910 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004911 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004912
4913 if (!adev)
4914 return 0;
4915
4916 pthread_mutex_lock(&adev_init_lock);
4917
4918 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004919 audio_extn_snd_mon_unregister_listener(adev);
4920 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004921 audio_route_free(adev->audio_route);
4922 free(adev->snd_dev_ref_cnt);
4923 platform_deinit(adev->platform);
4924 audio_extn_extspk_deinit(adev->extspk);
4925 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004926 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004927 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4928 pcm_params_free(adev->use_case_table[i]);
4929 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004930 if (adev->adm_deinit)
4931 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004932 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004933 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004934 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004935
4936 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004937
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004938 return 0;
4939}
4940
Glenn Kasten4f993392014-05-14 07:30:48 -07004941/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4942 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4943 * just that it _might_ work.
4944 */
4945static int period_size_is_plausible_for_low_latency(int period_size)
4946{
4947 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004948 case 48:
4949 case 96:
4950 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004951 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004952 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004953 case 240:
4954 case 320:
4955 case 480:
4956 return 1;
4957 default:
4958 return 0;
4959 }
4960}
4961
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004962static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4963{
4964 int card;
4965 card_status_t status;
4966
4967 if (!parms)
4968 return;
4969
4970 if (parse_snd_card_status(parms, &card, &status) < 0)
4971 return;
4972
4973 pthread_mutex_lock(&adev->lock);
4974 bool valid_cb = (card == adev->snd_card);
4975 if (valid_cb) {
4976 if (adev->card_status != status) {
4977 adev->card_status = status;
4978 platform_snd_card_update(adev->platform, status);
4979 }
4980 }
4981 pthread_mutex_unlock(&adev->lock);
4982 return;
4983}
4984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004985static int adev_open(const hw_module_t *module, const char *name,
4986 hw_device_t **device)
4987{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004988 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004989
Eric Laurent2bafff12016-03-17 12:17:23 -07004990 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004991 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004992 pthread_mutex_lock(&adev_init_lock);
4993 if (audio_device_ref_count != 0) {
4994 *device = &adev->device.common;
4995 audio_device_ref_count++;
4996 ALOGV("%s: returning existing instance of adev", __func__);
4997 ALOGV("%s: exit", __func__);
4998 pthread_mutex_unlock(&adev_init_lock);
4999 return 0;
5000 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005001 adev = calloc(1, sizeof(struct audio_device));
5002
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005003 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005005 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5006 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5007 adev->device.common.module = (struct hw_module_t *)module;
5008 adev->device.common.close = adev_close;
5009
5010 adev->device.init_check = adev_init_check;
5011 adev->device.set_voice_volume = adev_set_voice_volume;
5012 adev->device.set_master_volume = adev_set_master_volume;
5013 adev->device.get_master_volume = adev_get_master_volume;
5014 adev->device.set_master_mute = adev_set_master_mute;
5015 adev->device.get_master_mute = adev_get_master_mute;
5016 adev->device.set_mode = adev_set_mode;
5017 adev->device.set_mic_mute = adev_set_mic_mute;
5018 adev->device.get_mic_mute = adev_get_mic_mute;
5019 adev->device.set_parameters = adev_set_parameters;
5020 adev->device.get_parameters = adev_get_parameters;
5021 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5022 adev->device.open_output_stream = adev_open_output_stream;
5023 adev->device.close_output_stream = adev_close_output_stream;
5024 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005026 adev->device.close_input_stream = adev_close_input_stream;
5027 adev->device.dump = adev_dump;
5028
5029 /* Set the default route before the PCM stream is opened */
5030 pthread_mutex_lock(&adev->lock);
5031 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005032 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005033 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005034 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005035 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005036 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005037 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005038 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005039 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005040 pthread_mutex_unlock(&adev->lock);
5041
5042 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005043 adev->platform = platform_init(adev);
5044 if (!adev->platform) {
5045 free(adev->snd_dev_ref_cnt);
5046 free(adev);
5047 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5048 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005049 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005050 return -EINVAL;
5051 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005052 adev->extspk = audio_extn_extspk_init(adev);
5053
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005054 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5055 if (adev->visualizer_lib == NULL) {
5056 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5057 } else {
5058 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5059 adev->visualizer_start_output =
5060 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5061 "visualizer_hal_start_output");
5062 adev->visualizer_stop_output =
5063 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5064 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005065 }
5066
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005067 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5068 if (adev->offload_effects_lib == NULL) {
5069 ALOGW("%s: DLOPEN failed for %s", __func__,
5070 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5071 } else {
5072 ALOGV("%s: DLOPEN successful for %s", __func__,
5073 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5074 adev->offload_effects_start_output =
5075 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5076 "offload_effects_bundle_hal_start_output");
5077 adev->offload_effects_stop_output =
5078 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5079 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005080 }
5081
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005082 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5083 if (adev->adm_lib == NULL) {
5084 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5085 } else {
5086 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5087 adev->adm_init = (adm_init_t)
5088 dlsym(adev->adm_lib, "adm_init");
5089 adev->adm_deinit = (adm_deinit_t)
5090 dlsym(adev->adm_lib, "adm_deinit");
5091 adev->adm_register_input_stream = (adm_register_input_stream_t)
5092 dlsym(adev->adm_lib, "adm_register_input_stream");
5093 adev->adm_register_output_stream = (adm_register_output_stream_t)
5094 dlsym(adev->adm_lib, "adm_register_output_stream");
5095 adev->adm_deregister_stream = (adm_deregister_stream_t)
5096 dlsym(adev->adm_lib, "adm_deregister_stream");
5097 adev->adm_request_focus = (adm_request_focus_t)
5098 dlsym(adev->adm_lib, "adm_request_focus");
5099 adev->adm_abandon_focus = (adm_abandon_focus_t)
5100 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005101 adev->adm_set_config = (adm_set_config_t)
5102 dlsym(adev->adm_lib, "adm_set_config");
5103 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5104 dlsym(adev->adm_lib, "adm_request_focus_v2");
5105 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5106 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5107 adev->adm_on_routing_change = (adm_on_routing_change_t)
5108 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005109 }
5110
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005111 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005112 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005114 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005115
Andy Hung31aca912014-03-20 17:14:59 -07005116 if (k_enable_extended_precision)
5117 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005118
Glenn Kasten4f993392014-05-14 07:30:48 -07005119 char value[PROPERTY_VALUE_MAX];
5120 int trial;
5121 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5122 trial = atoi(value);
5123 if (period_size_is_plausible_for_low_latency(trial)) {
5124 pcm_config_low_latency.period_size = trial;
5125 pcm_config_low_latency.start_threshold = trial / 4;
5126 pcm_config_low_latency.avail_min = trial / 4;
5127 configured_low_latency_capture_period_size = trial;
5128 }
5129 }
5130 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5131 trial = atoi(value);
5132 if (period_size_is_plausible_for_low_latency(trial)) {
5133 configured_low_latency_capture_period_size = trial;
5134 }
5135 }
5136
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005137 // commented as full set of app type cfg is sent from platform
5138 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005139 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005140
5141 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5142 af_period_multiplier = atoi(value);
5143 if (af_period_multiplier < 0) {
5144 af_period_multiplier = 2;
5145 } else if (af_period_multiplier > 4) {
5146 af_period_multiplier = 4;
5147 }
5148 ALOGV("new period_multiplier = %d", af_period_multiplier);
5149 }
5150
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005151 audio_extn_tfa_98xx_init(adev);
5152
vivek mehta1a9b7c02015-06-25 11:49:38 -07005153 pthread_mutex_unlock(&adev_init_lock);
5154
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005155 if (adev->adm_init)
5156 adev->adm_data = adev->adm_init();
5157
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005158 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005159 audio_extn_snd_mon_init();
5160 pthread_mutex_lock(&adev->lock);
5161 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5162 adev->card_status = CARD_STATUS_ONLINE;
5163 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005164 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005165
Eric Laurent2bafff12016-03-17 12:17:23 -07005166 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005167 return 0;
5168}
5169
5170static struct hw_module_methods_t hal_module_methods = {
5171 .open = adev_open,
5172};
5173
5174struct audio_module HAL_MODULE_INFO_SYM = {
5175 .common = {
5176 .tag = HARDWARE_MODULE_TAG,
5177 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5178 .hal_api_version = HARDWARE_HAL_API_VERSION,
5179 .id = AUDIO_HARDWARE_MODULE_ID,
5180 .name = "QCOM Audio HAL",
5181 .author = "Code Aurora Forum",
5182 .methods = &hal_module_methods,
5183 },
5184};