blob: f58686502c357a451a936d656f88adb554ff0dc6 [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;
Yamit Mehtae3b99562016-09-16 22:44:00 +0530566 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800567 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800568 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500569 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000570 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
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);
Mikhail Naganov4ee6e3e2018-03-21 16:28:35 +0000596 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800597
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800598 ALOGV("%s: exit", __func__);
599 return 0;
600}
601
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800602int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700603 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700605 int i, num_devices = 0;
606 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800607 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800608 if (snd_device < SND_DEVICE_MIN ||
609 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800610 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800611 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800612 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700613
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700614 platform_send_audio_calibration(adev->platform, snd_device);
615
vivek mehtade4849c2016-03-03 17:23:38 -0800616 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700617 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700618 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800619 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 }
621
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700622 /* due to the possibility of calibration overwrite between listen
623 and audio, notify sound trigger hal before audio calibration is sent */
624 audio_extn_sound_trigger_update_device_status(snd_device,
625 ST_EVENT_SND_DEVICE_BUSY);
626
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700627 if (audio_extn_spkr_prot_is_enabled())
628 audio_extn_spkr_prot_calib_cancel(adev);
629
zhaoyang yin4211fad2015-06-04 21:13:25 +0800630 audio_extn_dsm_feedback_enable(adev, snd_device, true);
631
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700632 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800633 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700634 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
635 audio_extn_spkr_prot_is_enabled()) {
636 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800637 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700638 }
639 if (audio_extn_spkr_prot_start_processing(snd_device)) {
640 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800641 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700642 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700643 } else if (platform_can_split_snd_device(snd_device,
644 &num_devices,
645 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700646 for (i = 0; i < num_devices; i++) {
647 enable_snd_device(adev, new_snd_devices[i]);
648 }
vivek mehtab6506412015-08-07 16:55:17 -0700649 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700650 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800651 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
652 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
653 ALOGE(" %s: Invalid sound device returned", __func__);
654 goto on_error;
655 }
Ed Tam70b5c142016-03-21 19:14:29 -0700656
Eric Laurent2e140aa2016-06-30 17:14:46 -0700657 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800658 audio_route_apply_and_update_path(adev->audio_route, device_name);
659 }
660on_success:
661 adev->snd_dev_ref_cnt[snd_device]++;
662 ret_val = 0;
663on_error:
664 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800665}
666
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800667int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700668 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800669{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700670 int i, num_devices = 0;
671 snd_device_t new_snd_devices[2];
672
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800673 if (snd_device < SND_DEVICE_MIN ||
674 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800675 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800676 return -EINVAL;
677 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700678 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
679 ALOGE("%s: device ref cnt is already 0", __func__);
680 return -EINVAL;
681 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800682 audio_extn_tfa_98xx_disable_speaker(snd_device);
683
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 adev->snd_dev_ref_cnt[snd_device]--;
685 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800686 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700687 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
kevinshhsu7440d8c2018-01-14 22:25:38 +0800688 snd_device == SND_DEVICE_OUT_SPEAKER_SAFE ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700689 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700690 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
691 audio_extn_spkr_prot_is_enabled()) {
692 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700693
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700694 // FIXME b/65363602: bullhead is the only Nexus with audio_extn_spkr_prot_is_enabled()
695 // and does not use speaker swap. As this code causes a problem with device enable ref
696 // counting we remove it for now.
vivek mehtae59cfb22017-06-16 15:57:11 -0700697 // when speaker device is disabled, reset swap.
698 // will be renabled on usecase start
Eric Laurent3c1e4b72017-10-06 11:25:33 -0700699 // platform_set_swap_channels(adev, false);
vivek mehtae59cfb22017-06-16 15:57:11 -0700700
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700701 } else if (platform_can_split_snd_device(snd_device,
702 &num_devices,
703 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700704 for (i = 0; i < num_devices; i++) {
705 disable_snd_device(adev, new_snd_devices[i]);
706 }
vivek mehtab6506412015-08-07 16:55:17 -0700707 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700708 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800709 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
710 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
711 ALOGE(" %s: Invalid sound device returned", __func__);
712 return -EINVAL;
713 }
714
Eric Laurent2e140aa2016-06-30 17:14:46 -0700715 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800716 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700717 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700718 audio_extn_sound_trigger_update_device_status(snd_device,
719 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700720 }
vivek mehtab6506412015-08-07 16:55:17 -0700721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722 return 0;
723}
724
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700725/*
726 legend:
727 uc - existing usecase
728 new_uc - new usecase
729 d1, d11, d2 - SND_DEVICE enums
730 a1, a2 - corresponding ANDROID device enums
731 B, B1, B2 - backend strings
732
733case 1
734 uc->dev d1 (a1) B1
735 new_uc->dev d1 (a1), d2 (a2) B1, B2
736
737 resolution: disable and enable uc->dev on d1
738
739case 2
740 uc->dev d1 (a1) B1
741 new_uc->dev d11 (a1) B1
742
743 resolution: need to switch uc since d1 and d11 are related
744 (e.g. speaker and voice-speaker)
745 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
746
747case 3
748 uc->dev d1 (a1) B1
749 new_uc->dev d2 (a2) B2
750
751 resolution: no need to switch uc
752
753case 4
754 uc->dev d1 (a1) B
755 new_uc->dev d2 (a2) B
756
757 resolution: disable enable uc-dev on d2 since backends match
758 we cannot enable two streams on two different devices if they
759 share the same backend. e.g. if offload is on speaker device using
760 QUAD_MI2S backend and a low-latency stream is started on voice-handset
761 using the same backend, offload must also be switched to voice-handset.
762
763case 5
764 uc->dev d1 (a1) B
765 new_uc->dev d1 (a1), d2 (a2) B
766
767 resolution: disable enable uc-dev on d2 since backends match
768 we cannot enable two streams on two different devices if they
769 share the same backend.
770
771case 6
772 uc->dev d1 a1 B1
773 new_uc->dev d2 a1 B2
774
775 resolution: no need to switch
776
777case 7
778
779 uc->dev d1 (a1), d2 (a2) B1, B2
780 new_uc->dev d1 B1
781
782 resolution: no need to switch
783
784*/
785static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
786 struct audio_usecase *new_uc,
787 snd_device_t new_snd_device)
788{
789 audio_devices_t a1 = uc->stream.out->devices;
790 audio_devices_t a2 = new_uc->stream.out->devices;
791
792 snd_device_t d1 = uc->out_snd_device;
793 snd_device_t d2 = new_snd_device;
794
795 // Treat as a special case when a1 and a2 are not disjoint
796 if ((a1 != a2) && (a1 & a2)) {
797 snd_device_t d3[2];
798 int num_devices = 0;
799 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
800 &num_devices,
801 d3);
802 if (ret < 0) {
803 if (ret != -ENOSYS) {
804 ALOGW("%s failed to split snd_device %d",
805 __func__,
806 popcount(a1) > 1 ? d1 : d2);
807 }
808 goto end;
809 }
810
811 // NB: case 7 is hypothetical and isn't a practical usecase yet.
812 // But if it does happen, we need to give priority to d2 if
813 // the combo devices active on the existing usecase share a backend.
814 // This is because we cannot have a usecase active on a combo device
815 // and a new usecase requests one device in this combo pair.
816 if (platform_check_backends_match(d3[0], d3[1])) {
817 return d2; // case 5
818 } else {
819 return d1; // case 1
820 }
821 } else {
822 if (platform_check_backends_match(d1, d2)) {
823 return d2; // case 2, 4
824 } else {
825 return d1; // case 6, 3
826 }
827 }
828
829end:
830 return d2; // return whatever was calculated before.
831}
832
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700833static void check_and_route_playback_usecases(struct audio_device *adev,
834 struct audio_usecase *uc_info,
835 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836{
837 struct listnode *node;
838 struct audio_usecase *usecase;
839 bool switch_device[AUDIO_USECASE_MAX];
840 int i, num_uc_to_switch = 0;
841
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700842 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
843 uc_info,
844 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700845
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700846 /*
847 * This function is to make sure that all the usecases that are active on
848 * the hardware codec backend are always routed to any one device that is
849 * handled by the hardware codec.
850 * For example, if low-latency and deep-buffer usecases are currently active
851 * on speaker and out_set_parameters(headset) is received on low-latency
852 * output, then we have to make sure deep-buffer is also switched to headset,
853 * because of the limitation that both the devices cannot be enabled
854 * at the same time as they share the same backend.
855 */
856 /* Disable all the usecases on the shared backend other than the
857 specified usecase */
858 for (i = 0; i < AUDIO_USECASE_MAX; i++)
859 switch_device[i] = false;
860
861 list_for_each(node, &adev->usecase_list) {
862 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700863 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
864 continue;
865
866 if (force_routing ||
867 (usecase->out_snd_device != snd_device &&
Haynes Mathew George39c55dc2017-07-11 19:31:23 -0700868 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND ||
869 usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)) &&
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700870 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
872 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700873 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700874 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 switch_device[usecase->id] = true;
876 num_uc_to_switch++;
877 }
878 }
879
880 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 list_for_each(node, &adev->usecase_list) {
882 usecase = node_to_item(node, struct audio_usecase, list);
883 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700884 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900885 }
886 }
887
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700888 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900889 list_for_each(node, &adev->usecase_list) {
890 usecase = node_to_item(node, struct audio_usecase, list);
891 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700892 d_device = derive_playback_snd_device(usecase, uc_info,
893 snd_device);
894 enable_snd_device(adev, d_device);
895 /* Update the out_snd_device before enabling the audio route */
896 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700897 }
898 }
899
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700900 /* Re-route all the usecases on the shared backend other than the
901 specified usecase to new snd devices */
902 list_for_each(node, &adev->usecase_list) {
903 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700904 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700905 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700906 }
907 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700908 }
909}
910
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700911static void check_and_route_capture_usecases(struct audio_device *adev,
912 struct audio_usecase *uc_info,
913 snd_device_t snd_device)
914{
915 struct listnode *node;
916 struct audio_usecase *usecase;
917 bool switch_device[AUDIO_USECASE_MAX];
918 int i, num_uc_to_switch = 0;
919
vivek mehta4ed66e62016-04-15 23:33:34 -0700920 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
921
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700922 /*
923 * This function is to make sure that all the active capture usecases
924 * are always routed to the same input sound device.
925 * For example, if audio-record and voice-call usecases are currently
926 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
927 * is received for voice call then we have to make sure that audio-record
928 * usecase is also switched to earpiece i.e. voice-dmic-ef,
929 * because of the limitation that two devices cannot be enabled
930 * at the same time if they share the same backend.
931 */
932 for (i = 0; i < AUDIO_USECASE_MAX; i++)
933 switch_device[i] = false;
934
935 list_for_each(node, &adev->usecase_list) {
936 usecase = node_to_item(node, struct audio_usecase, list);
937 if (usecase->type != PCM_PLAYBACK &&
938 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700939 usecase->in_snd_device != snd_device &&
940 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700941 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
942 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700943 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700944 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700945 switch_device[usecase->id] = true;
946 num_uc_to_switch++;
947 }
948 }
949
950 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
953 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700954 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700955 }
956 }
957
958 list_for_each(node, &adev->usecase_list) {
959 usecase = node_to_item(node, struct audio_usecase, list);
960 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700961 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700962 }
963 }
964
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700965 /* Re-route all the usecases on the shared backend other than the
966 specified usecase to new snd devices */
967 list_for_each(node, &adev->usecase_list) {
968 usecase = node_to_item(node, struct audio_usecase, list);
969 /* Update the in_snd_device only before enabling the audio route */
970 if (switch_device[usecase->id] ) {
971 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700972 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700973 }
974 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700975 }
976}
977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800978/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700979static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700981 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700982 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983
984 switch (channels) {
985 /*
986 * Do not handle stereo output in Multi-channel cases
987 * Stereo case is handled in normal playback path
988 */
989 case 6:
990 ALOGV("%s: HDMI supports 5.1", __func__);
991 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
992 break;
993 case 8:
994 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
995 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
996 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
997 break;
998 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700999 ALOGE("HDMI does not support multi channel playback");
1000 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001001 break;
1002 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001003 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001004}
1005
Andy Hung18859412017-08-09 11:47:21 -07001006static ssize_t read_usb_sup_sample_rates(bool is_playback,
1007 uint32_t *supported_sample_rates,
1008 uint32_t max_rates)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001009{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001010 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1011 supported_sample_rates,
1012 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001013#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001014 for (ssize_t i=0; i<count; i++) {
1015 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1016 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001017 }
1018#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001019 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001020}
1021
Haynes Mathew George569b7482017-05-08 14:44:27 -07001022static int read_usb_sup_channel_masks(bool is_playback,
1023 audio_channel_mask_t *supported_channel_masks,
Eric Laurent74b55762017-07-09 17:04:53 -07001024 uint32_t max_masks)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001025{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001026 int channels = audio_extn_usb_get_max_channels(is_playback);
Eric Laurent74b55762017-07-09 17:04:53 -07001027 int channel_count;
1028 uint32_t num_masks = 0;
1029 if (channels > MAX_HIFI_CHANNEL_COUNT) {
1030 channels = MAX_HIFI_CHANNEL_COUNT;
Haynes Mathew George569b7482017-05-08 14:44:27 -07001031 }
Eric Laurent74b55762017-07-09 17:04:53 -07001032 if (is_playback) {
Andy Hung6c1afb12017-12-22 11:34:41 -08001033 // start from 2 channels as framework currently doesn't support mono.
1034 // TODO: consider only supporting channel index masks beyond stereo here.
1035 for (channel_count = FCC_2;
1036 channel_count <= channels && num_masks < max_masks;
1037 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001038 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
1039 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001040 for (channel_count = FCC_2;
1041 channel_count <= channels && num_masks < max_masks;
1042 ++channel_count) {
Eric Laurent74b55762017-07-09 17:04:53 -07001043 supported_channel_masks[num_masks++] =
1044 audio_channel_mask_for_index_assignment_from_count(channel_count);
1045 }
1046 } else {
1047 // For capture we report all supported channel masks from 1 channel up.
1048 channel_count = MIN_CHANNEL_COUNT;
1049 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1050 // indexed mask
1051 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1052 supported_channel_masks[num_masks++] =
1053 audio_channel_in_mask_from_count(channel_count);
1054 }
1055 }
Andy Hung6c1afb12017-12-22 11:34:41 -08001056#ifdef NDEBUG
1057 for (size_t i = 0; i < num_masks; ++i) {
1058 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1059 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
1060 }
1061#endif
Eric Laurent74b55762017-07-09 17:04:53 -07001062 return num_masks;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001063}
1064
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001065static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001066 audio_format_t *supported_formats,
1067 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001068{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001069 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001070 switch (bitwidth) {
1071 case 24:
1072 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001073 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001074 break;
1075 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001076 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001077 break;
1078 case 16:
1079 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001080 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001081 break;
1082 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001083 ALOGV("%s: %s supported format %d", __func__,
1084 is_playback ? "P" : "C", bitwidth);
1085 return 1;
1086}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001087
Haynes Mathew George569b7482017-05-08 14:44:27 -07001088static int read_usb_sup_params_and_compare(bool is_playback,
1089 audio_format_t *format,
1090 audio_format_t *supported_formats,
1091 uint32_t max_formats,
1092 audio_channel_mask_t *mask,
1093 audio_channel_mask_t *supported_channel_masks,
1094 uint32_t max_masks,
1095 uint32_t *rate,
1096 uint32_t *supported_sample_rates,
1097 uint32_t max_rates) {
1098 int ret = 0;
1099 int num_formats;
1100 int num_masks;
1101 int num_rates;
1102 int i;
1103
1104 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1105 max_formats);
1106 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1107 max_masks);
Eric Laurent74b55762017-07-09 17:04:53 -07001108
Haynes Mathew George569b7482017-05-08 14:44:27 -07001109 num_rates = read_usb_sup_sample_rates(is_playback,
1110 supported_sample_rates, max_rates);
1111
1112#define LUT(table, len, what, dflt) \
1113 for (i=0; i<len && (table[i] != what); i++); \
1114 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1115
1116 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1117 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1118 LUT(supported_sample_rates, num_rates, *rate, 0);
1119
1120#undef LUT
1121 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001122}
1123
Andy Hungd9653bd2017-08-01 19:31:39 -07001124static bool is_usb_ready(struct audio_device *adev, bool is_playback)
1125{
1126 // Check if usb is ready.
1127 // The usb device may have been removed quickly after insertion and hence
1128 // no longer available. This will show up as empty channel masks, or rates.
1129
1130 pthread_mutex_lock(&adev->lock);
1131 uint32_t supported_sample_rate;
1132
1133 // we consider usb ready if we can fetch at least one sample rate.
1134 const bool ready = read_usb_sup_sample_rates(
1135 is_playback, &supported_sample_rate, 1 /* max_rates */) > 0;
1136 pthread_mutex_unlock(&adev->lock);
1137 return ready;
1138}
1139
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001140static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1141{
1142 struct audio_usecase *usecase;
1143 struct listnode *node;
1144
1145 list_for_each(node, &adev->usecase_list) {
1146 usecase = node_to_item(node, struct audio_usecase, list);
1147 if (usecase->type == VOICE_CALL) {
1148 ALOGV("%s: usecase id %d", __func__, usecase->id);
1149 return usecase->id;
1150 }
1151 }
1152 return USECASE_INVALID;
1153}
1154
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001155struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1156 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001157{
1158 struct audio_usecase *usecase;
1159 struct listnode *node;
1160
1161 list_for_each(node, &adev->usecase_list) {
1162 usecase = node_to_item(node, struct audio_usecase, list);
1163 if (usecase->id == uc_id)
1164 return usecase;
1165 }
1166 return NULL;
1167}
1168
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001169int select_devices(struct audio_device *adev,
1170 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001171{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001172 snd_device_t out_snd_device = SND_DEVICE_NONE;
1173 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001174 struct audio_usecase *usecase = NULL;
1175 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001176 struct audio_usecase *hfp_usecase = NULL;
1177 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001178 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 int status = 0;
Eric Laurentf4520b02017-09-20 18:31:58 -07001180 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1181 USECASE_AUDIO_PLAYBACK_VOIP);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001182
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001183 usecase = get_usecase_from_list(adev, uc_id);
1184 if (usecase == NULL) {
1185 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1186 return -EINVAL;
1187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001188
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001189 if ((usecase->type == VOICE_CALL) ||
1190 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001191 out_snd_device = platform_get_output_snd_device(adev->platform,
1192 usecase->stream.out->devices);
1193 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001194 usecase->devices = usecase->stream.out->devices;
1195 } else {
1196 /*
1197 * If the voice call is active, use the sound devices of voice call usecase
1198 * so that it would not result any device switch. All the usecases will
1199 * be switched to new device when select_devices() is called for voice call
1200 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001201 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001202 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001203 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001204 vc_usecase = get_usecase_from_list(adev,
1205 get_voice_usecase_id_from_list(adev));
1206 if ((vc_usecase != NULL) &&
1207 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1208 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001209 in_snd_device = vc_usecase->in_snd_device;
1210 out_snd_device = vc_usecase->out_snd_device;
1211 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001212 } else if (audio_extn_hfp_is_active(adev)) {
1213 hfp_ucid = audio_extn_hfp_get_usecase();
1214 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1215 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1216 in_snd_device = hfp_usecase->in_snd_device;
1217 out_snd_device = hfp_usecase->out_snd_device;
1218 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001219 }
1220 if (usecase->type == PCM_PLAYBACK) {
1221 usecase->devices = usecase->stream.out->devices;
1222 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001223 if (out_snd_device == SND_DEVICE_NONE) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001224 struct stream_out *voip_out = adev->primary_output;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001225
Eric Laurentb23d5282013-05-14 15:27:20 -07001226 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001227 usecase->stream.out->devices);
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001228
1229 if (voip_usecase)
1230 voip_out = voip_usecase->stream.out;
1231
1232 if (usecase->stream.out == voip_out &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001233 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001234 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001235 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001236 select_devices(adev, adev->active_input->usecase);
1237 }
1238 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001239 } else if (usecase->type == PCM_CAPTURE) {
1240 usecase->devices = usecase->stream.in->device;
1241 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001242 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001243 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001244 if (adev->active_input &&
1245 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1246 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001247
1248 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1249 USECASE_AUDIO_PLAYBACK_VOIP);
1250
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001251 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001252 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1253 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
carter_hsu1e1ebbf2017-08-15 11:39:55 +08001254 } else if (voip_usecase) {
1255 out_device = voip_usecase->stream.out->devices;
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001256 } else if (adev->primary_output) {
1257 out_device = adev->primary_output->devices;
1258 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001259 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001260 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001261 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001262 }
1263 }
1264
1265 if (out_snd_device == usecase->out_snd_device &&
1266 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001267 return 0;
1268 }
1269
Eric Laurent2bafff12016-03-17 12:17:23 -07001270 if (out_snd_device != SND_DEVICE_NONE &&
1271 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1272 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1273 __func__,
1274 use_case_table[uc_id],
1275 adev->last_logged_snd_device[uc_id][0],
1276 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1277 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1278 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1279 -1,
1280 out_snd_device,
1281 platform_get_snd_device_name(out_snd_device),
1282 platform_get_snd_device_acdb_id(out_snd_device));
1283 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1284 }
1285 if (in_snd_device != SND_DEVICE_NONE &&
1286 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1287 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1288 __func__,
1289 use_case_table[uc_id],
1290 adev->last_logged_snd_device[uc_id][1],
1291 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1292 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1293 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1294 -1,
1295 in_snd_device,
1296 platform_get_snd_device_name(in_snd_device),
1297 platform_get_snd_device_acdb_id(in_snd_device));
1298 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1299 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001300
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001301 /*
1302 * Limitation: While in call, to do a device switch we need to disable
1303 * and enable both RX and TX devices though one of them is same as current
1304 * device.
1305 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001306 if ((usecase->type == VOICE_CALL) &&
1307 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1308 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001309 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001310 /* Disable sidetone only if voice call already exists */
1311 if (voice_is_call_state_active(adev))
1312 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001313 }
1314
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001315 /* Disable current sound devices */
1316 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001317 disable_audio_route(adev, usecase);
1318 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001319 }
1320
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001321 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001322 disable_audio_route(adev, usecase);
1323 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001324 }
1325
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001326 /* Applicable only on the targets that has external modem.
1327 * New device information should be sent to modem before enabling
1328 * the devices to reduce in-call device switch time.
1329 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001330 if ((usecase->type == VOICE_CALL) &&
1331 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1332 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001333 status = platform_switch_voice_call_enable_device_config(adev->platform,
1334 out_snd_device,
1335 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001336 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001337
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338 /* Enable new sound devices */
1339 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001340 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001341 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001342 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001343 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 }
1345
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001346 if (in_snd_device != SND_DEVICE_NONE) {
1347 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001348 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001349 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001350
Eric Laurentb23d5282013-05-14 15:27:20 -07001351 if (usecase->type == VOICE_CALL)
1352 status = platform_switch_voice_call_device_post(adev->platform,
1353 out_snd_device,
1354 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001355
sangwoo170731f2013-06-08 15:36:36 +09001356 usecase->in_snd_device = in_snd_device;
1357 usecase->out_snd_device = out_snd_device;
1358
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001359 audio_extn_tfa_98xx_set_mode();
1360
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001361 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001362
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001363 /* Applicable only on the targets that has external modem.
1364 * Enable device command should be sent to modem only after
1365 * enabling voice call mixer controls
1366 */
vivek mehta765eb642015-08-07 19:46:06 -07001367 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001368 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1369 out_snd_device,
1370 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001371 /* Enable sidetone only if voice call already exists */
1372 if (voice_is_call_state_active(adev))
1373 voice_set_sidetone(adev, out_snd_device, true);
1374 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001375
Eric Laurentf4520b02017-09-20 18:31:58 -07001376 if (usecase == voip_usecase) {
1377 struct stream_out *voip_out = voip_usecase->stream.out;
1378 audio_extn_utils_send_app_type_gain(adev,
1379 voip_out->app_type_cfg.app_type,
1380 &voip_out->app_type_cfg.gain[0]);
1381 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001382 return status;
1383}
1384
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001385static int stop_input_stream(struct stream_in *in)
1386{
1387 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388 struct audio_usecase *uc_info;
1389 struct audio_device *adev = in->dev;
1390
Eric Laurent994a6932013-07-17 11:51:42 -07001391 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001392 in->usecase, use_case_table[in->usecase]);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07001393
1394 if (adev->active_input) {
1395 if (adev->active_input->usecase == in->usecase) {
1396 adev->active_input = NULL;
1397 } else {
1398 ALOGW("%s adev->active_input->usecase %s, v/s in->usecase %s",
1399 __func__,
1400 use_case_table[adev->active_input->usecase],
1401 use_case_table[in->usecase]);
1402 }
1403 }
1404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001405 uc_info = get_usecase_from_list(adev, in->usecase);
1406 if (uc_info == NULL) {
1407 ALOGE("%s: Could not find the usecase (%d) in the list",
1408 __func__, in->usecase);
1409 return -EINVAL;
1410 }
1411
vivek mehta781065c2017-04-04 12:55:01 -07001412 /* Close in-call recording streams */
1413 voice_check_and_stop_incall_rec_usecase(adev, in);
1414
Eric Laurent150dbfe2013-02-27 14:31:02 -08001415 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001416 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001417
1418 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001419 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001420
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001421 list_remove(&uc_info->list);
1422 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001423
Eric Laurent994a6932013-07-17 11:51:42 -07001424 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001425 return ret;
1426}
1427
1428int start_input_stream(struct stream_in *in)
1429{
1430 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001431 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001432 struct audio_usecase *uc_info;
1433 struct audio_device *adev = in->dev;
1434
Eric Laurent994a6932013-07-17 11:51:42 -07001435 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001436
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001437 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1438 return -EIO;
1439
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001440 if (in->card_status == CARD_STATUS_OFFLINE ||
1441 adev->card_status == CARD_STATUS_OFFLINE) {
1442 ALOGW("in->card_status or adev->card_status offline, try again");
1443 ret = -EAGAIN;
1444 goto error_config;
1445 }
1446
vivek mehta781065c2017-04-04 12:55:01 -07001447 /* Check if source matches incall recording usecase criteria */
1448 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1449 if (ret)
1450 goto error_config;
1451 else
1452 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1453
Eric Laurentb23d5282013-05-14 15:27:20 -07001454 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455 if (in->pcm_device_id < 0) {
1456 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1457 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001458 ret = -EINVAL;
1459 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001460 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001461
1462 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1464 uc_info->id = in->usecase;
1465 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001466 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 uc_info->devices = in->device;
1468 uc_info->in_snd_device = SND_DEVICE_NONE;
1469 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001471 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001472
Wei Wangf4837d52017-11-21 14:51:20 -08001473 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001474 audio_extn_perf_lock_acquire();
1475
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001476 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477
Eric Laurent0e46adf2016-12-16 12:49:24 -08001478 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001479 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001480 ALOGE("%s: pcm stream not ready", __func__);
1481 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001482 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001483 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001484 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001485 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1486 goto error_open;
1487 }
1488 } else {
1489 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1490 unsigned int pcm_open_retry_count = 0;
1491
1492 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1493 flags |= PCM_MMAP | PCM_NOIRQ;
1494 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1495 } else if (in->realtime) {
1496 flags |= PCM_MMAP | PCM_NOIRQ;
1497 }
1498
1499 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1500 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1501
1502 while (1) {
1503 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1504 flags, &in->config);
1505 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1506 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1507 if (in->pcm != NULL) {
1508 pcm_close(in->pcm);
1509 in->pcm = NULL;
1510 }
1511 if (pcm_open_retry_count-- == 0) {
1512 ret = -EIO;
1513 goto error_open;
1514 }
1515 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1516 continue;
1517 }
1518 break;
1519 }
1520
1521 ALOGV("%s: pcm_prepare", __func__);
1522 ret = pcm_prepare(in->pcm);
1523 if (ret < 0) {
1524 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001525 pcm_close(in->pcm);
1526 in->pcm = NULL;
1527 goto error_open;
1528 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001529 if (in->realtime) {
1530 ret = pcm_start(in->pcm);
1531 if (ret < 0) {
1532 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1533 pcm_close(in->pcm);
1534 in->pcm = NULL;
1535 goto error_open;
1536 }
1537 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001538 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001539 register_in_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001540 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001541 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001542 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001543
Eric Laurent0e46adf2016-12-16 12:49:24 -08001544 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001545
1546error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547 stop_input_stream(in);
Wei Wangf4837d52017-11-21 14:51:20 -08001548 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001549 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001550
1551error_config:
1552 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001553 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001554 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555}
1556
Eric Laurenta1478072015-09-21 17:21:52 -07001557void lock_input_stream(struct stream_in *in)
1558{
1559 pthread_mutex_lock(&in->pre_lock);
1560 pthread_mutex_lock(&in->lock);
1561 pthread_mutex_unlock(&in->pre_lock);
1562}
1563
1564void lock_output_stream(struct stream_out *out)
1565{
1566 pthread_mutex_lock(&out->pre_lock);
1567 pthread_mutex_lock(&out->lock);
1568 pthread_mutex_unlock(&out->pre_lock);
1569}
1570
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001571/* must be called with out->lock locked */
1572static int send_offload_cmd_l(struct stream_out* out, int command)
1573{
1574 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1575
1576 ALOGVV("%s %d", __func__, command);
1577
1578 cmd->cmd = command;
1579 list_add_tail(&out->offload_cmd_list, &cmd->node);
1580 pthread_cond_signal(&out->offload_cond);
1581 return 0;
1582}
1583
1584/* must be called iwth out->lock locked */
1585static void stop_compressed_output_l(struct stream_out *out)
1586{
1587 out->offload_state = OFFLOAD_STATE_IDLE;
1588 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001589 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001590 if (out->compr != NULL) {
1591 compress_stop(out->compr);
1592 while (out->offload_thread_blocked) {
1593 pthread_cond_wait(&out->cond, &out->lock);
1594 }
1595 }
1596}
1597
1598static void *offload_thread_loop(void *context)
1599{
1600 struct stream_out *out = (struct stream_out *) context;
1601 struct listnode *item;
1602
1603 out->offload_state = OFFLOAD_STATE_IDLE;
1604 out->playback_started = 0;
1605
1606 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1607 set_sched_policy(0, SP_FOREGROUND);
1608 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1609
1610 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001611 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001612 for (;;) {
1613 struct offload_cmd *cmd = NULL;
1614 stream_callback_event_t event;
1615 bool send_callback = false;
1616
1617 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1618 __func__, list_empty(&out->offload_cmd_list),
1619 out->offload_state);
1620 if (list_empty(&out->offload_cmd_list)) {
1621 ALOGV("%s SLEEPING", __func__);
1622 pthread_cond_wait(&out->offload_cond, &out->lock);
1623 ALOGV("%s RUNNING", __func__);
1624 continue;
1625 }
1626
1627 item = list_head(&out->offload_cmd_list);
1628 cmd = node_to_item(item, struct offload_cmd, node);
1629 list_remove(item);
1630
1631 ALOGVV("%s STATE %d CMD %d out->compr %p",
1632 __func__, out->offload_state, cmd->cmd, out->compr);
1633
1634 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1635 free(cmd);
1636 break;
1637 }
1638
1639 if (out->compr == NULL) {
1640 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001641 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001642 pthread_cond_signal(&out->cond);
1643 continue;
1644 }
1645 out->offload_thread_blocked = true;
1646 pthread_mutex_unlock(&out->lock);
1647 send_callback = false;
1648 switch(cmd->cmd) {
1649 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1650 compress_wait(out->compr, -1);
1651 send_callback = true;
1652 event = STREAM_CBK_EVENT_WRITE_READY;
1653 break;
1654 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001655 compress_next_track(out->compr);
1656 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001657 send_callback = true;
1658 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001659 /* Resend the metadata for next iteration */
1660 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001661 break;
1662 case OFFLOAD_CMD_DRAIN:
1663 compress_drain(out->compr);
1664 send_callback = true;
1665 event = STREAM_CBK_EVENT_DRAIN_READY;
1666 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001667 case OFFLOAD_CMD_ERROR:
1668 send_callback = true;
1669 event = STREAM_CBK_EVENT_ERROR;
1670 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001671 default:
1672 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1673 break;
1674 }
Eric Laurenta1478072015-09-21 17:21:52 -07001675 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001676 out->offload_thread_blocked = false;
1677 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001678 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001679 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001680 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001681 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001682 free(cmd);
1683 }
1684
1685 pthread_cond_signal(&out->cond);
1686 while (!list_empty(&out->offload_cmd_list)) {
1687 item = list_head(&out->offload_cmd_list);
1688 list_remove(item);
1689 free(node_to_item(item, struct offload_cmd, node));
1690 }
1691 pthread_mutex_unlock(&out->lock);
1692
1693 return NULL;
1694}
1695
1696static int create_offload_callback_thread(struct stream_out *out)
1697{
1698 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1699 list_init(&out->offload_cmd_list);
1700 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1701 offload_thread_loop, out);
1702 return 0;
1703}
1704
1705static int destroy_offload_callback_thread(struct stream_out *out)
1706{
Eric Laurenta1478072015-09-21 17:21:52 -07001707 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001708 stop_compressed_output_l(out);
1709 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1710
1711 pthread_mutex_unlock(&out->lock);
1712 pthread_join(out->offload_thread, (void **) NULL);
1713 pthread_cond_destroy(&out->offload_cond);
1714
1715 return 0;
1716}
1717
Eric Laurent07eeafd2013-10-06 12:52:49 -07001718static bool allow_hdmi_channel_config(struct audio_device *adev)
1719{
1720 struct listnode *node;
1721 struct audio_usecase *usecase;
1722 bool ret = true;
1723
1724 list_for_each(node, &adev->usecase_list) {
1725 usecase = node_to_item(node, struct audio_usecase, list);
1726 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1727 /*
1728 * If voice call is already existing, do not proceed further to avoid
1729 * disabling/enabling both RX and TX devices, CSD calls, etc.
1730 * Once the voice call done, the HDMI channels can be configured to
1731 * max channels of remaining use cases.
1732 */
1733 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001734 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001735 __func__);
1736 ret = false;
1737 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001738 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1739 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001740 "no change in HDMI channels", __func__);
1741 ret = false;
1742 break;
1743 }
1744 }
1745 }
1746 return ret;
1747}
1748
1749static int check_and_set_hdmi_channels(struct audio_device *adev,
1750 unsigned int channels)
1751{
1752 struct listnode *node;
1753 struct audio_usecase *usecase;
1754
1755 /* Check if change in HDMI channel config is allowed */
1756 if (!allow_hdmi_channel_config(adev))
1757 return 0;
1758
1759 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001760 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001761 return 0;
1762 }
1763
1764 platform_set_hdmi_channels(adev->platform, channels);
1765 adev->cur_hdmi_channels = channels;
1766
1767 /*
1768 * Deroute all the playback streams routed to HDMI so that
1769 * the back end is deactivated. Note that backend will not
1770 * be deactivated if any one stream is connected to it.
1771 */
1772 list_for_each(node, &adev->usecase_list) {
1773 usecase = node_to_item(node, struct audio_usecase, list);
1774 if (usecase->type == PCM_PLAYBACK &&
1775 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001776 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001777 }
1778 }
1779
1780 /*
1781 * Enable all the streams disabled above. Now the HDMI backend
1782 * will be activated with new channel configuration
1783 */
1784 list_for_each(node, &adev->usecase_list) {
1785 usecase = node_to_item(node, struct audio_usecase, list);
1786 if (usecase->type == PCM_PLAYBACK &&
1787 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001788 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001789 }
1790 }
1791
1792 return 0;
1793}
1794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001795static int stop_output_stream(struct stream_out *out)
1796{
1797 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 struct audio_usecase *uc_info;
1799 struct audio_device *adev = out->dev;
1800
Eric Laurent994a6932013-07-17 11:51:42 -07001801 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001802 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001803 uc_info = get_usecase_from_list(adev, out->usecase);
1804 if (uc_info == NULL) {
1805 ALOGE("%s: Could not find the usecase (%d) in the list",
1806 __func__, out->usecase);
1807 return -EINVAL;
1808 }
1809
Haynes Mathew George41f86652014-06-17 14:22:15 -07001810 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1811 if (adev->visualizer_stop_output != NULL)
1812 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1813 if (adev->offload_effects_stop_output != NULL)
1814 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001815 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1816 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1817 audio_low_latency_hint_end();
Haynes Mathew George41f86652014-06-17 14:22:15 -07001818 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001819
Eric Laurent150dbfe2013-02-27 14:31:02 -08001820 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001821 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822
1823 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001824 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001826 list_remove(&uc_info->list);
1827 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001828
Eric Laurent0499d4f2014-08-25 22:39:29 -05001829 audio_extn_extspk_update(adev->extspk);
1830
Eric Laurent07eeafd2013-10-06 12:52:49 -07001831 /* Must be called after removing the usecase from list */
1832 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1833 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
Haynes Mathew George0ecfe3d2017-08-04 15:36:09 -07001834 else if (out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
1835 struct listnode *node;
1836 struct audio_usecase *usecase;
1837 list_for_each(node, &adev->usecase_list) {
1838 usecase = node_to_item(node, struct audio_usecase, list);
1839 if (usecase->devices & AUDIO_DEVICE_OUT_SPEAKER)
1840 select_devices(adev, usecase->id);
1841 }
1842 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001843
Eric Laurent994a6932013-07-17 11:51:42 -07001844 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 return ret;
1846}
1847
1848int start_output_stream(struct stream_out *out)
1849{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 struct audio_usecase *uc_info;
1852 struct audio_device *adev = out->dev;
1853
Eric Laurent994a6932013-07-17 11:51:42 -07001854 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001855 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001856
1857 if (out->card_status == CARD_STATUS_OFFLINE ||
1858 adev->card_status == CARD_STATUS_OFFLINE) {
1859 ALOGW("out->card_status or adev->card_status offline, try again");
1860 ret = -EAGAIN;
1861 goto error_config;
1862 }
1863
Eric Laurentb23d5282013-05-14 15:27:20 -07001864 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 if (out->pcm_device_id < 0) {
1866 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1867 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001868 ret = -EINVAL;
1869 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870 }
1871
1872 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1873 uc_info->id = out->usecase;
1874 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001875 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001876 uc_info->devices = out->devices;
1877 uc_info->in_snd_device = SND_DEVICE_NONE;
1878 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879
Eric Laurent07eeafd2013-10-06 12:52:49 -07001880 /* This must be called before adding this usecase to the list */
1881 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1882 check_and_set_hdmi_channels(adev, out->config.channels);
1883
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001884 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885
Wei Wangf4837d52017-11-21 14:51:20 -08001886 audio_streaming_hint_start();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001887 audio_extn_perf_lock_acquire();
1888
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 select_devices(adev, out->usecase);
1890
Eric Laurent0499d4f2014-08-25 22:39:29 -05001891 audio_extn_extspk_update(adev->extspk);
1892
Andy Hung31aca912014-03-20 17:14:59 -07001893 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001894 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001895 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1896 out->pcm = NULL;
1897 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1898 COMPRESS_IN, &out->compr_config);
1899 if (out->compr && !is_compress_ready(out->compr)) {
1900 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1901 compress_close(out->compr);
1902 out->compr = NULL;
1903 ret = -EIO;
1904 goto error_open;
1905 }
1906 if (out->offload_callback)
1907 compress_nonblock(out->compr, out->non_blocking);
1908
1909 if (adev->visualizer_start_output != NULL)
1910 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1911 if (adev->offload_effects_start_output != NULL)
1912 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1913 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001914 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001915 ALOGE("%s: pcm stream not ready", __func__);
1916 goto error_open;
1917 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001918 ret = pcm_start(out->pcm);
1919 if (ret < 0) {
1920 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1921 goto error_open;
1922 }
1923 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001924 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001925 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001926
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001927 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1928 flags |= PCM_MMAP | PCM_NOIRQ;
1929 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001930 } else if (out->realtime) {
1931 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001932 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001933
1934 while (1) {
1935 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1936 flags, &out->config);
1937 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1938 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1939 if (out->pcm != NULL) {
1940 pcm_close(out->pcm);
1941 out->pcm = NULL;
1942 }
1943 if (pcm_open_retry_count-- == 0) {
1944 ret = -EIO;
1945 goto error_open;
1946 }
1947 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1948 continue;
1949 }
1950 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001951 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001952 ALOGV("%s: pcm_prepare", __func__);
1953 if (pcm_is_ready(out->pcm)) {
1954 ret = pcm_prepare(out->pcm);
1955 if (ret < 0) {
1956 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1957 pcm_close(out->pcm);
1958 out->pcm = NULL;
1959 goto error_open;
1960 }
1961 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001962 if (out->realtime) {
1963 ret = pcm_start(out->pcm);
1964 if (ret < 0) {
1965 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1966 pcm_close(out->pcm);
1967 out->pcm = NULL;
1968 goto error_open;
1969 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001970 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001971 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001972 register_out_stream(out);
Wei Wangf4837d52017-11-21 14:51:20 -08001973 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001974 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001975 audio_extn_tfa_98xx_enable_speaker();
vivek mehtae59cfb22017-06-16 15:57:11 -07001976
Haynes Mathew Georged9ca7962017-12-01 16:29:56 -08001977 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
1978 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
1979 audio_low_latency_hint_start();
1980 }
1981
vivek mehtae59cfb22017-06-16 15:57:11 -07001982 // consider a scenario where on pause lower layers are tear down.
1983 // so on resume, swap mixer control need to be sent only when
1984 // backend is active, hence rather than sending from enable device
1985 // sending it from start of streamtream
1986
1987 platform_set_swap_channels(adev, true);
1988
Eric Laurent994a6932013-07-17 11:51:42 -07001989 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001990 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001991error_open:
Wei Wangf4837d52017-11-21 14:51:20 -08001992 audio_streaming_hint_end();
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001993 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001995error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001996 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997}
1998
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999static int check_input_parameters(uint32_t sample_rate,
2000 audio_format_t format,
Eric Laurent74b55762017-07-09 17:04:53 -07002001 int channel_count, bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002002{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002003 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
2004 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
Eric Laurent74b55762017-07-09 17:04:53 -07002005 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) &&
2006 !(is_usb_hifi && (format == AUDIO_FORMAT_PCM_32_BIT))) {
vivek mehtadae44712015-07-27 14:13:18 -07002007 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
2008 return -EINVAL;
2009 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010
Eric Laurent74b55762017-07-09 17:04:53 -07002011 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
2012 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07002013 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
Eric Laurent74b55762017-07-09 17:04:53 -07002014 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
vivek mehtadae44712015-07-27 14:13:18 -07002015 return -EINVAL;
2016 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002017
2018 switch (sample_rate) {
2019 case 8000:
2020 case 11025:
2021 case 12000:
2022 case 16000:
2023 case 22050:
2024 case 24000:
2025 case 32000:
2026 case 44100:
2027 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07002028 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002029 break;
2030 default:
vivek mehtadae44712015-07-27 14:13:18 -07002031 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002032 return -EINVAL;
2033 }
2034
2035 return 0;
2036}
2037
vivek mehtaa68fea62017-06-08 19:04:02 -07002038static size_t get_stream_buffer_size(size_t duration_ms,
2039 uint32_t sample_rate,
2040 audio_format_t format,
2041 int channel_count,
2042 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043{
2044 size_t size = 0;
2045
vivek mehtaa68fea62017-06-08 19:04:02 -07002046 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002047 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07002048 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07002049
2050 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002051
Glenn Kasten4f993392014-05-14 07:30:48 -07002052 /* make sure the size is multiple of 32 bytes
2053 * At 48 kHz mono 16-bit PCM:
2054 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
2055 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
2056 */
2057 size += 0x1f;
2058 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07002059
2060 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002061}
2062
2063static uint32_t out_get_sample_rate(const struct audio_stream *stream)
2064{
2065 struct stream_out *out = (struct stream_out *)stream;
2066
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002067 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002068}
2069
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002070static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071{
2072 return -ENOSYS;
2073}
2074
2075static size_t out_get_buffer_size(const struct audio_stream *stream)
2076{
2077 struct stream_out *out = (struct stream_out *)stream;
2078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002079 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2080 return out->compr_config.fragment_size;
2081 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002082 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07002083 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002084}
2085
2086static uint32_t out_get_channels(const struct audio_stream *stream)
2087{
2088 struct stream_out *out = (struct stream_out *)stream;
2089
2090 return out->channel_mask;
2091}
2092
2093static audio_format_t out_get_format(const struct audio_stream *stream)
2094{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002095 struct stream_out *out = (struct stream_out *)stream;
2096
2097 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002098}
2099
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002100static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002101{
2102 return -ENOSYS;
2103}
2104
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002105/* must be called with out->lock locked */
2106static int out_standby_l(struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002107{
2108 struct stream_out *out = (struct stream_out *)stream;
2109 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002110 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002113 if (adev->adm_deregister_stream)
2114 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002115 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002117 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2118 if (out->pcm) {
2119 pcm_close(out->pcm);
2120 out->pcm = NULL;
2121 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002122 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002123 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002124 out->playback_started = false;
2125 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002126 } else {
2127 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002128 out->gapless_mdata.encoder_delay = 0;
2129 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 if (out->compr != NULL) {
2131 compress_close(out->compr);
2132 out->compr = NULL;
2133 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002134 }
Phil Burkbc991042017-02-24 08:06:44 -08002135 if (do_stop) {
2136 stop_output_stream(out);
2137 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002138 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139 }
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002140 return 0;
2141}
2142
2143static int out_standby(struct audio_stream *stream)
2144{
2145 struct stream_out *out = (struct stream_out *)stream;
2146
2147 ALOGV("%s: enter: usecase(%d: %s)", __func__,
2148 out->usecase, use_case_table[out->usecase]);
2149
2150 lock_output_stream(out);
2151 out_standby_l(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002153 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 return 0;
2155}
2156
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002157static int out_on_error(struct audio_stream *stream)
2158{
2159 struct stream_out *out = (struct stream_out *)stream;
2160 struct audio_device *adev = out->dev;
2161 bool do_standby = false;
2162
2163 lock_output_stream(out);
2164 if (!out->standby) {
2165 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2166 stop_compressed_output_l(out);
2167 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2168 } else
2169 do_standby = true;
2170 }
2171 pthread_mutex_unlock(&out->lock);
2172
2173 if (do_standby)
2174 return out_standby(&out->stream.common);
2175
2176 return 0;
2177}
2178
Andy Hung7401c7c2016-09-21 12:41:21 -07002179static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180{
Andy Hung7401c7c2016-09-21 12:41:21 -07002181 struct stream_out *out = (struct stream_out *)stream;
2182
2183 // We try to get the lock for consistency,
2184 // but it isn't necessary for these variables.
2185 // If we're not in standby, we may be blocked on a write.
2186 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2187 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2188 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2189
2190 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002191 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002192 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002193
2194 // dump error info
2195 (void)error_log_dump(
2196 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198 return 0;
2199}
2200
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002201static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2202{
2203 int ret = 0;
2204 char value[32];
2205 struct compr_gapless_mdata tmp_mdata;
2206
2207 if (!out || !parms) {
2208 return -EINVAL;
2209 }
2210
2211 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2212 if (ret >= 0) {
2213 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2214 } else {
2215 return -EINVAL;
2216 }
2217
2218 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2219 if (ret >= 0) {
2220 tmp_mdata.encoder_padding = atoi(value);
2221 } else {
2222 return -EINVAL;
2223 }
2224
2225 out->gapless_mdata = tmp_mdata;
2226 out->send_new_metadata = 1;
2227 ALOGV("%s new encoder delay %u and padding %u", __func__,
2228 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2229
2230 return 0;
2231}
2232
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002233static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2234{
2235 return out == adev->primary_output || out == adev->voice_tx_output;
2236}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002237
Kevin Rocard1e02c882017-08-09 15:26:07 -07002238static int get_alive_usb_card(struct str_parms* parms) {
2239 int card;
2240 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
2241 !audio_extn_usb_alive(card)) {
2242 return card;
2243 }
2244 return -ENODEV;
2245}
2246
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002247static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2248{
2249 struct stream_out *out = (struct stream_out *)stream;
2250 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002251 struct audio_usecase *usecase;
2252 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253 struct str_parms *parms;
2254 char value[32];
2255 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002256 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002257 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258
Eric Laurent2e140aa2016-06-30 17:14:46 -07002259 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002260 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261 parms = str_parms_create_str(kvpairs);
2262 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2263 if (ret >= 0) {
2264 val = atoi(value);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002265
Eric Laurenta1478072015-09-21 17:21:52 -07002266 lock_output_stream(out);
Kevin Rocard2ba1a472017-08-10 20:26:09 -07002267
2268 // The usb driver needs to be closed after usb device disconnection
2269 // otherwise audio is no longer played on the new usb devices.
2270 // By forcing the stream in standby, the usb stack refcount drops to 0
2271 // and the driver is closed.
2272 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD && val == AUDIO_DEVICE_NONE &&
2273 audio_is_usb_out_device(out->devices)) {
2274 ALOGD("%s() putting the usb device in standby after disconnection", __func__);
2275 out_standby_l(&out->stream.common);
2276 }
2277
Eric Laurent150dbfe2013-02-27 14:31:02 -08002278 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002280 /*
2281 * When HDMI cable is unplugged the music playback is paused and
2282 * the policy manager sends routing=0. But the audioflinger
2283 * continues to write data until standby time (3sec).
2284 * As the HDMI core is turned off, the write gets blocked.
2285 * Avoid this by routing audio to speaker until standby.
2286 */
2287 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2288 val == AUDIO_DEVICE_NONE) {
2289 val = AUDIO_DEVICE_OUT_SPEAKER;
2290 }
2291
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002292 audio_devices_t new_dev = val;
2293
2294 // Workaround: If routing to an non existing usb device, fail gracefully
2295 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07002296 int card;
2297 if (audio_is_usb_out_device(new_dev) &&
2298 (card = get_alive_usb_card(parms)) >= 0) {
2299
2300 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002301 pthread_mutex_unlock(&adev->lock);
2302 pthread_mutex_unlock(&out->lock);
2303 status = -ENOSYS;
2304 goto routing_fail;
2305 }
2306
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002307 /*
2308 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002309 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002310 * the select_devices(). But how do we undo this?
2311 *
2312 * For example, music playback is active on headset (deep-buffer usecase)
2313 * and if we go to ringtones and select a ringtone, low-latency usecase
2314 * will be started on headset+speaker. As we can't enable headset+speaker
2315 * and headset devices at the same time, select_devices() switches the music
2316 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2317 * So when the ringtone playback is completed, how do we undo the same?
2318 *
2319 * We are relying on the out_set_parameters() call on deep-buffer output,
2320 * once the ringtone playback is ended.
2321 * NOTE: We should not check if the current devices are same as new devices.
2322 * Because select_devices() must be called to switch back the music
2323 * playback to headset.
2324 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002325 if (new_dev != AUDIO_DEVICE_NONE) {
2326 bool same_dev = out->devices == new_dev;
2327 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002328
Eric Laurenta7657192014-10-09 21:09:33 -07002329 if (output_drives_call(adev, out)) {
2330 if (!voice_is_in_call(adev)) {
2331 if (adev->mode == AUDIO_MODE_IN_CALL) {
2332 adev->current_call_output = out;
2333 ret = voice_start_call(adev);
2334 }
2335 } else {
2336 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002337 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002338 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002339 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002340
2341 if (!out->standby) {
2342 if (!same_dev) {
2343 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002344 // inform adm before actual routing to prevent glitches.
2345 if (adev->adm_on_routing_change) {
2346 adev->adm_on_routing_change(adev->adm_data,
2347 out->handle);
2348 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002349 }
2350 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002351 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002352
2353 // on device switch force swap, lower functions will make sure
2354 // to check if swap is allowed or not.
2355
2356 if (!same_dev)
2357 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002358 }
2359
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002360 }
2361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002362 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002363 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002364
2365 /*handles device and call state changes*/
2366 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002367 }
Kevin Rocardf9f241e2017-08-07 19:21:36 -07002368 routing_fail:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002369
2370 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2371 parse_compress_metadata(out, parms);
2372 }
2373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002375 ALOGV("%s: exit: code(%d)", __func__, status);
2376 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377}
2378
Haynes Mathew George569b7482017-05-08 14:44:27 -07002379static bool stream_get_parameter_channels(struct str_parms *query,
2380 struct str_parms *reply,
2381 audio_channel_mask_t *supported_channel_masks) {
2382 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002383 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002384 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002385 size_t i, j;
2386
2387 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2388 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002389 value[0] = '\0';
2390 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002391 while (supported_channel_masks[i] != 0) {
2392 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2393 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002394 if (!first) {
2395 strcat(value, "|");
2396 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002397 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398 first = false;
2399 break;
2400 }
2401 }
2402 i++;
2403 }
2404 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002405 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002406 return ret >= 0;
2407}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002408
Haynes Mathew George569b7482017-05-08 14:44:27 -07002409static bool stream_get_parameter_formats(struct str_parms *query,
2410 struct str_parms *reply,
2411 audio_format_t *supported_formats) {
2412 int ret = -1;
2413 char value[256];
2414 int i;
2415
2416 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2417 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002418 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002419 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002420 case AUDIO_FORMAT_PCM_16_BIT:
2421 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2422 break;
2423 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2424 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2425 break;
2426 case AUDIO_FORMAT_PCM_32_BIT:
2427 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2428 break;
2429 default:
2430 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002431 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002432 break;
2433 }
2434 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002435 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002436 return ret >= 0;
2437}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002438
Haynes Mathew George569b7482017-05-08 14:44:27 -07002439static bool stream_get_parameter_rates(struct str_parms *query,
2440 struct str_parms *reply,
2441 uint32_t *supported_sample_rates) {
2442
2443 int i;
2444 char value[256];
2445 int ret = -1;
2446 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2447 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002448 value[0] = '\0';
2449 i=0;
2450 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002451 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002452 int avail = sizeof(value) - cursor;
2453 ret = snprintf(value + cursor, avail, "%s%d",
2454 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002455 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002456 if (ret < 0 || ret >= avail) {
2457 // if cursor is at the last element of the array
2458 // overwrite with \0 is duplicate work as
2459 // snprintf already put a \0 in place.
2460 // else
2461 // we had space to write the '|' at value[cursor]
2462 // (which will be overwritten) or no space to fill
2463 // the first element (=> cursor == 0)
2464 value[cursor] = '\0';
2465 break;
2466 }
2467 cursor += ret;
2468 ++i;
2469 }
2470 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2471 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002472 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002473 return ret >= 0;
2474}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002475
Haynes Mathew George569b7482017-05-08 14:44:27 -07002476static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2477{
2478 struct stream_out *out = (struct stream_out *)stream;
2479 struct str_parms *query = str_parms_create_str(keys);
2480 char *str;
2481 struct str_parms *reply = str_parms_create();
2482 bool replied = false;
2483 ALOGV("%s: enter: keys - %s", __func__, keys);
2484
2485 replied |= stream_get_parameter_channels(query, reply,
2486 &out->supported_channel_masks[0]);
2487 replied |= stream_get_parameter_formats(query, reply,
2488 &out->supported_formats[0]);
2489 replied |= stream_get_parameter_rates(query, reply,
2490 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002491 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 str = str_parms_to_str(reply);
2493 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002494 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495 }
2496 str_parms_destroy(query);
2497 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002498 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499 return str;
2500}
2501
2502static uint32_t out_get_latency(const struct audio_stream_out *stream)
2503{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002504 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 struct stream_out *out = (struct stream_out *)stream;
2506
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002507 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2508 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002509 else if ((out->realtime) ||
2510 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002511 // since the buffer won't be filled up faster than realtime,
2512 // return a smaller number
2513 period_ms = (out->af_period_multiplier * out->config.period_size *
2514 1000) / (out->config.rate);
2515 hw_delay = platform_render_latency(out->usecase)/1000;
2516 return period_ms + hw_delay;
2517 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002518
2519 return (out->config.period_count * out->config.period_size * 1000) /
2520 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002521}
2522
2523static int out_set_volume(struct audio_stream_out *stream, float left,
2524 float right)
2525{
Eric Laurenta9024de2013-04-04 09:19:12 -07002526 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002527 int volume[2];
2528
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002529 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002530 /* only take left channel into account: the API is for stereo anyway */
2531 out->muted = (left == 0.0f);
2532 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002533 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2534 const char *mixer_ctl_name = "Compress Playback Volume";
2535 struct audio_device *adev = out->dev;
2536 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002537 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2538 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002539 /* try with the control based on device id */
2540 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2541 PCM_PLAYBACK);
2542 char ctl_name[128] = {0};
2543 snprintf(ctl_name, sizeof(ctl_name),
2544 "Compress Playback %d Volume", pcm_device_id);
2545 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2546 if (!ctl) {
2547 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2548 return -EINVAL;
2549 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002550 }
2551 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2552 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2553 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2554 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002555 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002556 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2557 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2558 if (!out->standby) {
2559 // if in standby, cached volume will be sent after stream is opened
2560 audio_extn_utils_send_app_type_gain(out->dev,
2561 out->app_type_cfg.app_type,
2562 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002563 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002564 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002565 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 return -ENOSYS;
2568}
2569
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002570// note: this call is safe only if the stream_cb is
2571// removed first in close_output_stream (as is done now).
2572static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2573{
2574 if (!stream || !parms)
2575 return;
2576
2577 struct stream_out *out = (struct stream_out *)stream;
2578 struct audio_device *adev = out->dev;
2579
2580 card_status_t status;
2581 int card;
2582 if (parse_snd_card_status(parms, &card, &status) < 0)
2583 return;
2584
2585 pthread_mutex_lock(&adev->lock);
2586 bool valid_cb = (card == adev->snd_card);
2587 pthread_mutex_unlock(&adev->lock);
2588
2589 if (!valid_cb)
2590 return;
2591
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002592 lock_output_stream(out);
2593 if (out->card_status != status)
2594 out->card_status = status;
2595 pthread_mutex_unlock(&out->lock);
2596
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002597 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2598 use_case_table[out->usecase],
2599 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2600
2601 if (status == CARD_STATUS_OFFLINE)
2602 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002603
2604 return;
2605}
2606
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002607#ifdef NO_AUDIO_OUT
2608static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002609 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002610{
2611 struct stream_out *out = (struct stream_out *)stream;
2612
2613 /* No Output device supported other than BT for playback.
2614 * Sleep for the amount of buffer duration
2615 */
Eric Laurenta1478072015-09-21 17:21:52 -07002616 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002617 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2618 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002619 out_get_sample_rate(&out->stream.common));
2620 pthread_mutex_unlock(&out->lock);
2621 return bytes;
2622}
2623#endif
2624
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002625static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2626 size_t bytes)
2627{
2628 struct stream_out *out = (struct stream_out *)stream;
2629 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002630 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002631 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632
Eric Laurenta1478072015-09-21 17:21:52 -07002633 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002634 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002635 const size_t frame_size = audio_stream_out_frame_size(stream);
2636 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002637
Eric Laurent0e46adf2016-12-16 12:49:24 -08002638 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2639 error_code = ERROR_CODE_WRITE;
2640 goto exit;
2641 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002643 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002644 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 ret = start_output_stream(out);
vivek mehta40125092017-08-21 18:48:51 -07002646
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002647 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002649 out->standby = true;
vivek mehta40125092017-08-21 18:48:51 -07002650 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 goto exit;
2652 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002653
vivek mehta40125092017-08-21 18:48:51 -07002654 // after standby always force set last known cal step
2655 // dont change level anywhere except at the audio_hw_send_gain_dep_calibration
2656 ALOGD("%s: retry previous failed cal level set", __func__);
2657 send_gain_dep_calibration_l();
2658 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002661 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002662 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002663 if (out->send_new_metadata) {
2664 ALOGVV("send new gapless metadata");
2665 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2666 out->send_new_metadata = 0;
2667 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002668 unsigned int avail;
2669 struct timespec tstamp;
2670 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2671 /* Do not limit write size if the available frames count is unknown */
2672 if (ret != 0) {
2673 avail = bytes;
2674 }
2675 if (avail == 0) {
2676 ret = 0;
2677 } else {
2678 if (avail > bytes) {
2679 avail = bytes;
2680 }
2681 ret = compress_write(out->compr, buffer, avail);
2682 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2683 __func__, avail, ret);
2684 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002685
Eric Laurent6e895242013-09-05 16:10:57 -07002686 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002687 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2688 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002689 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002690 compress_start(out->compr);
2691 out->playback_started = 1;
2692 out->offload_state = OFFLOAD_STATE_PLAYING;
2693 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002694 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002695 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002696 } else {
2697 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002698 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002699 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002700 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002701 return ret;
2702 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002703 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002704 if (out->pcm) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002705 size_t bytes_to_write = bytes;
2706
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002707 if (out->muted)
2708 memset((void *)buffer, 0, bytes);
Eric Laurentad2dde92017-09-20 18:27:31 -07002709 // FIXME: this can be removed once audio flinger mixer supports mono output
Nadav Bar3d72cfc2018-01-07 12:19:24 +02002710 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP || out->usecase == USECASE_INCALL_MUSIC_UPLINK) {
Eric Laurentad2dde92017-09-20 18:27:31 -07002711 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
2712 int16_t *src = (int16_t *)buffer;
2713 int16_t *dst = (int16_t *)buffer;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002714
Eric Laurentad2dde92017-09-20 18:27:31 -07002715 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
2716 out->format != AUDIO_FORMAT_PCM_16_BIT,
2717 "out_write called for VOIP use case with wrong properties");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002718
Eric Laurentad2dde92017-09-20 18:27:31 -07002719 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
2720 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
2721 }
2722 bytes_to_write /= 2;
2723 }
2724 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes_to_write);
2725
Glenn Kasten5a59dff2018-02-22 08:05:35 -08002726 long ns = (frames * (int64_t) NANOS_PER_SECOND) / out->config.rate;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002727 request_out_focus(out, ns);
2728
2729 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2730 if (use_mmap)
Eric Laurentad2dde92017-09-20 18:27:31 -07002731 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002732 else
Eric Laurentad2dde92017-09-20 18:27:31 -07002733 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002734
Haynes Mathew George03c40102016-01-29 17:57:48 -08002735 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002736 } else {
2737 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002738 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 }
2740
2741exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002742 // For PCM we always consume the buffer and return #bytes regardless of ret.
2743 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002744 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002745 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002746 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002747
Andy Hung7401c7c2016-09-21 12:41:21 -07002748 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002749 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002750 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2751 ALOGE_IF(out->pcm != NULL,
2752 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002753 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002754 // usleep not guaranteed for values over 1 second but we don't limit here.
2755 }
2756 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 pthread_mutex_unlock(&out->lock);
2759
2760 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002761 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002762 if (sleeptime_us != 0)
2763 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764 }
2765 return bytes;
2766}
2767
2768static int out_get_render_position(const struct audio_stream_out *stream,
2769 uint32_t *dsp_frames)
2770{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002771 struct stream_out *out = (struct stream_out *)stream;
2772 *dsp_frames = 0;
2773 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002774 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002775 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002776 unsigned long frames = 0;
2777 // TODO: check return value
2778 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2779 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002780 ALOGVV("%s rendered frames %d sample_rate %d",
2781 __func__, *dsp_frames, out->sample_rate);
2782 }
2783 pthread_mutex_unlock(&out->lock);
2784 return 0;
2785 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002786 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787}
2788
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002789static int out_add_audio_effect(const struct audio_stream *stream __unused,
2790 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791{
2792 return 0;
2793}
2794
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002795static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2796 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797{
2798 return 0;
2799}
2800
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002801static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2802 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002804 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805}
2806
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002807static int out_get_presentation_position(const struct audio_stream_out *stream,
2808 uint64_t *frames, struct timespec *timestamp)
2809{
2810 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002811 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002812 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002813
Eric Laurenta1478072015-09-21 17:21:52 -07002814 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002815
Eric Laurent949a0892013-09-20 09:20:13 -07002816 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2817 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002818 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002819 compress_get_tstamp(out->compr, &dsp_frames,
2820 &out->sample_rate);
2821 ALOGVV("%s rendered frames %ld sample_rate %d",
2822 __func__, dsp_frames, out->sample_rate);
2823 *frames = dsp_frames;
2824 ret = 0;
2825 /* this is the best we can do */
2826 clock_gettime(CLOCK_MONOTONIC, timestamp);
2827 }
2828 } else {
2829 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002830 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002831 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2832 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002833 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002834 // This adjustment accounts for buffering after app processor.
2835 // It is based on estimated DSP latency per use case, rather than exact.
2836 signed_frames -=
2837 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2838
Eric Laurent949a0892013-09-20 09:20:13 -07002839 // It would be unusual for this value to be negative, but check just in case ...
2840 if (signed_frames >= 0) {
2841 *frames = signed_frames;
2842 ret = 0;
2843 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002844 }
2845 }
2846 }
2847
2848 pthread_mutex_unlock(&out->lock);
2849
2850 return ret;
2851}
2852
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002853static int out_set_callback(struct audio_stream_out *stream,
2854 stream_callback_t callback, void *cookie)
2855{
2856 struct stream_out *out = (struct stream_out *)stream;
2857
2858 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002859 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860 out->offload_callback = callback;
2861 out->offload_cookie = cookie;
2862 pthread_mutex_unlock(&out->lock);
2863 return 0;
2864}
2865
2866static int out_pause(struct audio_stream_out* stream)
2867{
2868 struct stream_out *out = (struct stream_out *)stream;
2869 int status = -ENOSYS;
2870 ALOGV("%s", __func__);
2871 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002872 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002873 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2874 status = compress_pause(out->compr);
2875 out->offload_state = OFFLOAD_STATE_PAUSED;
2876 }
2877 pthread_mutex_unlock(&out->lock);
2878 }
2879 return status;
2880}
2881
2882static int out_resume(struct audio_stream_out* stream)
2883{
2884 struct stream_out *out = (struct stream_out *)stream;
2885 int status = -ENOSYS;
2886 ALOGV("%s", __func__);
2887 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2888 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002889 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002890 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2891 status = compress_resume(out->compr);
2892 out->offload_state = OFFLOAD_STATE_PLAYING;
2893 }
2894 pthread_mutex_unlock(&out->lock);
2895 }
2896 return status;
2897}
2898
2899static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2900{
2901 struct stream_out *out = (struct stream_out *)stream;
2902 int status = -ENOSYS;
2903 ALOGV("%s", __func__);
2904 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002905 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002906 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2907 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2908 else
2909 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2910 pthread_mutex_unlock(&out->lock);
2911 }
2912 return status;
2913}
2914
2915static int out_flush(struct audio_stream_out* stream)
2916{
2917 struct stream_out *out = (struct stream_out *)stream;
2918 ALOGV("%s", __func__);
2919 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002920 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 stop_compressed_output_l(out);
2922 pthread_mutex_unlock(&out->lock);
2923 return 0;
2924 }
2925 return -ENOSYS;
2926}
2927
Eric Laurent0e46adf2016-12-16 12:49:24 -08002928static int out_stop(const struct audio_stream_out* stream)
2929{
2930 struct stream_out *out = (struct stream_out *)stream;
2931 struct audio_device *adev = out->dev;
2932 int ret = -ENOSYS;
2933
2934 ALOGV("%s", __func__);
2935 pthread_mutex_lock(&adev->lock);
2936 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2937 out->playback_started && out->pcm != NULL) {
2938 pcm_stop(out->pcm);
2939 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002940 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002941 }
2942 pthread_mutex_unlock(&adev->lock);
2943 return ret;
2944}
2945
2946static int out_start(const struct audio_stream_out* stream)
2947{
2948 struct stream_out *out = (struct stream_out *)stream;
2949 struct audio_device *adev = out->dev;
2950 int ret = -ENOSYS;
2951
2952 ALOGV("%s", __func__);
2953 pthread_mutex_lock(&adev->lock);
2954 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2955 !out->playback_started && out->pcm != NULL) {
2956 ret = start_output_stream(out);
2957 if (ret == 0) {
2958 out->playback_started = true;
2959 }
2960 }
2961 pthread_mutex_unlock(&adev->lock);
2962 return ret;
2963}
2964
Phil Burkbc991042017-02-24 08:06:44 -08002965/*
2966 * Modify config->period_count based on min_size_frames
2967 */
2968static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2969{
2970 int periodCountRequested = (min_size_frames + config->period_size - 1)
2971 / config->period_size;
2972 int periodCount = MMAP_PERIOD_COUNT_MIN;
2973
2974 ALOGV("%s original config.period_size = %d config.period_count = %d",
2975 __func__, config->period_size, config->period_count);
2976
2977 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2978 periodCount *= 2;
2979 }
2980 config->period_count = periodCount;
2981
2982 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2983}
2984
Eric Laurent0e46adf2016-12-16 12:49:24 -08002985static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2986 int32_t min_size_frames,
2987 struct audio_mmap_buffer_info *info)
2988{
2989 struct stream_out *out = (struct stream_out *)stream;
2990 struct audio_device *adev = out->dev;
2991 int ret = 0;
2992 unsigned int offset1;
2993 unsigned int frames1;
2994 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002995 uint32_t mmap_size;
2996 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002997
2998 ALOGV("%s", __func__);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08002999 lock_output_stream(out);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003000 pthread_mutex_lock(&adev->lock);
3001
3002 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003003 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003004 ret = -EINVAL;
3005 goto exit;
3006 }
3007 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003008 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003009 ret = -ENOSYS;
3010 goto exit;
3011 }
3012 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
3013 if (out->pcm_device_id < 0) {
3014 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3015 __func__, out->pcm_device_id, out->usecase);
3016 ret = -EINVAL;
3017 goto exit;
3018 }
Phil Burkbc991042017-02-24 08:06:44 -08003019
3020 adjust_mmap_period_count(&out->config, min_size_frames);
3021
Eric Laurent0e46adf2016-12-16 12:49:24 -08003022 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3023 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
3024 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
3025 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
3026 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3027 step = "open";
3028 ret = -ENODEV;
3029 goto exit;
3030 }
3031 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
3032 if (ret < 0) {
3033 step = "begin";
3034 goto exit;
3035 }
3036 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003037 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003038 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003039 ret = platform_get_mmap_data_fd(adev->platform,
3040 out->pcm_device_id, 0 /*playback*/,
3041 &info->shared_memory_fd,
3042 &mmap_size);
3043 if (ret < 0) {
3044 // Fall back to non exclusive mode
3045 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
3046 } else {
3047 if (mmap_size < buffer_size) {
3048 step = "mmap";
3049 goto exit;
3050 }
3051 // FIXME: indicate exclusive mode support by returning a negative buffer size
3052 info->buffer_size_frames *= -1;
3053 }
3054 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003055
3056 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
3057 if (ret < 0) {
3058 step = "commit";
3059 goto exit;
3060 }
Phil Burkbc991042017-02-24 08:06:44 -08003061
3062 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003063 ret = 0;
3064
3065 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3066 __func__, info->shared_memory_address, info->buffer_size_frames);
3067
3068exit:
3069 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003070 if (out->pcm == NULL) {
3071 ALOGE("%s: %s - %d", __func__, step, ret);
3072 } else {
3073 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003074 pcm_close(out->pcm);
3075 out->pcm = NULL;
3076 }
3077 }
3078 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003079 pthread_mutex_unlock(&out->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003080 return ret;
3081}
3082
3083static int out_get_mmap_position(const struct audio_stream_out *stream,
3084 struct audio_mmap_position *position)
3085{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003086 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003087 struct stream_out *out = (struct stream_out *)stream;
3088 ALOGVV("%s", __func__);
3089 if (position == NULL) {
3090 return -EINVAL;
3091 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003092 lock_output_stream(out);
3093 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP ||
3094 out->pcm == NULL) {
3095 ret = -ENOSYS;
3096 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003097 }
3098
3099 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003100 ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003101 if (ret < 0) {
3102 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003103 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003104 }
Andy Hungfc044e12017-03-20 09:24:22 -07003105 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003106exit:
3107 pthread_mutex_unlock(&out->lock);
3108 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003109}
3110
3111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112/** audio_stream_in implementation **/
3113static uint32_t in_get_sample_rate(const struct audio_stream *stream)
3114{
3115 struct stream_in *in = (struct stream_in *)stream;
3116
3117 return in->config.rate;
3118}
3119
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003120static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121{
3122 return -ENOSYS;
3123}
3124
3125static size_t in_get_buffer_size(const struct audio_stream *stream)
3126{
3127 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003128 return in->config.period_size * in->af_period_multiplier *
3129 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130}
3131
3132static uint32_t in_get_channels(const struct audio_stream *stream)
3133{
3134 struct stream_in *in = (struct stream_in *)stream;
3135
3136 return in->channel_mask;
3137}
3138
vivek mehta4ed66e62016-04-15 23:33:34 -07003139static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140{
vivek mehta4ed66e62016-04-15 23:33:34 -07003141 struct stream_in *in = (struct stream_in *)stream;
3142 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143}
3144
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003145static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146{
3147 return -ENOSYS;
3148}
3149
3150static int in_standby(struct audio_stream *stream)
3151{
3152 struct stream_in *in = (struct stream_in *)stream;
3153 struct audio_device *adev = in->dev;
3154 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08003155 bool do_stop = true;
3156
Eric Laurent994a6932013-07-17 11:51:42 -07003157 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003158
3159 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003160
3161 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003162 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003163 audio_extn_sound_trigger_stop_lab(in);
3164 in->standby = true;
3165 }
3166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003168 if (adev->adm_deregister_stream)
3169 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3170
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003171 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003173 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003174 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003175 in->capture_started = false;
3176 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003177 if (in->pcm) {
3178 pcm_close(in->pcm);
3179 in->pcm = NULL;
3180 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003181 adev->enable_voicerx = false;
3182 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003183 if (do_stop) {
3184 status = stop_input_stream(in);
3185 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003186 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 }
3188 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003189 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 return status;
3191}
3192
Andy Hungd13f0d32017-06-12 13:58:37 -07003193static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194{
Andy Hungd13f0d32017-06-12 13:58:37 -07003195 struct stream_in *in = (struct stream_in *)stream;
3196
3197 // We try to get the lock for consistency,
3198 // but it isn't necessary for these variables.
3199 // If we're not in standby, we may be blocked on a read.
3200 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3201 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3202 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3203 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3204
3205 if (locked) {
3206 pthread_mutex_unlock(&in->lock);
3207 }
3208
3209 // dump error info
3210 (void)error_log_dump(
3211 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003212 return 0;
3213}
3214
3215static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3216{
3217 struct stream_in *in = (struct stream_in *)stream;
3218 struct audio_device *adev = in->dev;
3219 struct str_parms *parms;
3220 char *str;
3221 char value[32];
3222 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003223 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224
Eric Laurent994a6932013-07-17 11:51:42 -07003225 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226 parms = str_parms_create_str(kvpairs);
3227
3228 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3229
Eric Laurenta1478072015-09-21 17:21:52 -07003230 lock_input_stream(in);
3231
Eric Laurent150dbfe2013-02-27 14:31:02 -08003232 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 if (ret >= 0) {
3234 val = atoi(value);
3235 /* no audio source uses val == 0 */
3236 if ((in->source != val) && (val != 0)) {
3237 in->source = val;
3238 }
3239 }
3240
3241 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003242
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243 if (ret >= 0) {
3244 val = atoi(value);
Haynes Mathew George8ea04722017-07-25 17:41:49 -07003245 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003246
3247 // Workaround: If routing to an non existing usb device, fail gracefully
3248 // The routing request will otherwise block during 10 second
Kevin Rocard1e02c882017-08-09 15:26:07 -07003249 int card;
3250 if (audio_is_usb_in_device(val) &&
3251 (card = get_alive_usb_card(parms)) >= 0) {
3252
3253 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
Kevin Rocardf9f241e2017-08-07 19:21:36 -07003254 status = -ENOSYS;
3255 } else {
3256
3257 in->device = val;
3258 /* If recording is in progress, change the tx device to new device */
3259 if (!in->standby) {
3260 ALOGV("update input routing change");
3261 // inform adm before actual routing to prevent glitches.
3262 if (adev->adm_on_routing_change) {
3263 adev->adm_on_routing_change(adev->adm_data,
3264 in->capture_handle);
3265 }
3266 select_devices(adev, in->usecase);
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003267 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003268 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269 }
3270 }
3271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003273 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274
3275 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003276 ALOGV("%s: exit: status(%d)", __func__, status);
3277 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003278}
3279
Haynes Mathew George569b7482017-05-08 14:44:27 -07003280static char* in_get_parameters(const struct audio_stream *stream,
3281 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003282{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003283 struct stream_in *in = (struct stream_in *)stream;
3284 struct str_parms *query = str_parms_create_str(keys);
3285 char *str;
3286 struct str_parms *reply = str_parms_create();
3287 bool replied = false;
3288
3289 ALOGV("%s: enter: keys - %s", __func__, keys);
3290 replied |= stream_get_parameter_channels(query, reply,
3291 &in->supported_channel_masks[0]);
3292 replied |= stream_get_parameter_formats(query, reply,
3293 &in->supported_formats[0]);
3294 replied |= stream_get_parameter_rates(query, reply,
3295 &in->supported_sample_rates[0]);
3296 if (replied) {
3297 str = str_parms_to_str(reply);
3298 } else {
Kevin Rocard7e876682017-07-26 14:17:26 -07003299 str = strdup("");
Haynes Mathew George569b7482017-05-08 14:44:27 -07003300 }
3301 str_parms_destroy(query);
3302 str_parms_destroy(reply);
3303 ALOGV("%s: exit: returns - %s", __func__, str);
3304 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003305}
3306
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003307static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003309 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003310}
3311
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003312static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3313{
3314 if (!stream || !parms)
3315 return;
3316
3317 struct stream_in *in = (struct stream_in *)stream;
3318 struct audio_device *adev = in->dev;
3319
3320 card_status_t status;
3321 int card;
3322 if (parse_snd_card_status(parms, &card, &status) < 0)
3323 return;
3324
3325 pthread_mutex_lock(&adev->lock);
3326 bool valid_cb = (card == adev->snd_card);
3327 pthread_mutex_unlock(&adev->lock);
3328
3329 if (!valid_cb)
3330 return;
3331
3332 lock_input_stream(in);
3333 if (in->card_status != status)
3334 in->card_status = status;
3335 pthread_mutex_unlock(&in->lock);
3336
3337 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3338 use_case_table[in->usecase],
3339 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3340
3341 // a better solution would be to report error back to AF and let
3342 // it put the stream to standby
3343 if (status == CARD_STATUS_OFFLINE)
3344 in_standby(&in->stream.common);
3345
3346 return;
3347}
3348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3350 size_t bytes)
3351{
3352 struct stream_in *in = (struct stream_in *)stream;
3353 struct audio_device *adev = in->dev;
3354 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003355 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003356 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357
Eric Laurenta1478072015-09-21 17:21:52 -07003358 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003359 const size_t frame_size = audio_stream_in_frame_size(stream);
3360 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003361
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003362 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003363 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003364 /* Read from sound trigger HAL */
3365 audio_extn_sound_trigger_read(in, buffer, bytes);
3366 pthread_mutex_unlock(&in->lock);
3367 return bytes;
3368 }
3369
Eric Laurent0e46adf2016-12-16 12:49:24 -08003370 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3371 ret = -ENOSYS;
3372 goto exit;
3373 }
3374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003375 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003376 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003378 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 goto exit;
3381 }
3382 in->standby = 0;
3383 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384
Andy Hungd13f0d32017-06-12 13:58:37 -07003385 // errors that occur here are read errors.
3386 error_code = ERROR_CODE_READ;
3387
Haynes Mathew George03c40102016-01-29 17:57:48 -08003388 //what's the duration requested by the client?
3389 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3390 in->config.rate;
3391 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003392
Haynes Mathew George03c40102016-01-29 17:57:48 -08003393 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003395 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003396 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003397 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003398 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003399 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003400 if (ret < 0) {
3401 ALOGE("Failed to read w/err %s", strerror(errno));
3402 ret = -errno;
3403 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003404 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3405 if (bytes % 4 == 0) {
3406 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3407 int_buf_stream = buffer;
3408 for (size_t itt=0; itt < bytes/4 ; itt++) {
3409 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003410 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003411 } else {
3412 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3413 ret = -EINVAL;
3414 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003415 }
3416 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 }
3418
Haynes Mathew George03c40102016-01-29 17:57:48 -08003419 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003420
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421 /*
3422 * Instead of writing zeroes here, we could trust the hardware
3423 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003424 * 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 -08003425 */
Haynes Mathew George988277b2017-12-20 14:14:33 -08003426 if (ret == 0 && adev->mic_muted &&
3427 !voice_is_in_call_rec_stream(in) &&
3428 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003429 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003430 in->frames_muted += frames;
3431 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432
3433exit:
3434 pthread_mutex_unlock(&in->lock);
3435
3436 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003437 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438 in_standby(&in->stream.common);
3439 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003440 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003441 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003442 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003443 }
3444 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003445 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003446 }
3447 return bytes;
3448}
3449
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003450static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451{
3452 return 0;
3453}
3454
Andy Hung6ebe5962016-01-15 17:46:57 -08003455static int in_get_capture_position(const struct audio_stream_in *stream,
3456 int64_t *frames, int64_t *time)
3457{
3458 if (stream == NULL || frames == NULL || time == NULL) {
3459 return -EINVAL;
3460 }
3461 struct stream_in *in = (struct stream_in *)stream;
3462 int ret = -ENOSYS;
3463
3464 lock_input_stream(in);
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003465 // note: ST sessions do not close the alsa pcm driver synchronously
3466 // on standby. Therefore, we may return an error even though the
3467 // pcm stream is still opened.
3468 if (in->standby) {
3469 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
3470 "%s stream in standby but pcm not NULL for non ST session", __func__);
3471 goto exit;
3472 }
Andy Hung6ebe5962016-01-15 17:46:57 -08003473 if (in->pcm) {
3474 struct timespec timestamp;
3475 unsigned int avail;
3476 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3477 *frames = in->frames_read + avail;
3478 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3479 ret = 0;
3480 }
3481 }
Haynes Mathew George7aa29e32017-12-11 18:10:36 -08003482exit:
Andy Hung6ebe5962016-01-15 17:46:57 -08003483 pthread_mutex_unlock(&in->lock);
3484 return ret;
3485}
3486
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003487static int add_remove_audio_effect(const struct audio_stream *stream,
3488 effect_handle_t effect,
3489 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003491 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003492 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003493 int status = 0;
3494 effect_descriptor_t desc;
3495
3496 status = (*effect)->get_descriptor(effect, &desc);
3497 if (status != 0)
3498 return status;
3499
Eric Laurenta1478072015-09-21 17:21:52 -07003500 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003501 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003502 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003503 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003504 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003505 in->enable_aec != enable &&
3506 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3507 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003508 if (!enable)
3509 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003510 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3511 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3512 adev->enable_voicerx = enable;
3513 struct audio_usecase *usecase;
3514 struct listnode *node;
3515 list_for_each(node, &adev->usecase_list) {
3516 usecase = node_to_item(node, struct audio_usecase, list);
vivek mehtac07684b2017-09-15 13:31:12 -07003517 if (usecase->type == PCM_PLAYBACK)
vivek mehta733c1df2016-04-04 15:09:24 -07003518 select_devices(adev, usecase->id);
Eric Laurentcefbbac2014-09-04 13:54:10 -05003519 }
3520 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003521 if (!in->standby)
3522 select_devices(in->dev, in->usecase);
3523 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003524 if (in->enable_ns != enable &&
3525 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3526 in->enable_ns = enable;
3527 if (!in->standby)
3528 select_devices(in->dev, in->usecase);
3529 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003530 pthread_mutex_unlock(&in->dev->lock);
3531 pthread_mutex_unlock(&in->lock);
3532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533 return 0;
3534}
3535
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003536static int in_add_audio_effect(const struct audio_stream *stream,
3537 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538{
Eric Laurent994a6932013-07-17 11:51:42 -07003539 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003540 return add_remove_audio_effect(stream, effect, true);
3541}
3542
3543static int in_remove_audio_effect(const struct audio_stream *stream,
3544 effect_handle_t effect)
3545{
Eric Laurent994a6932013-07-17 11:51:42 -07003546 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003547 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003548}
3549
Eric Laurent0e46adf2016-12-16 12:49:24 -08003550static int in_stop(const struct audio_stream_in* stream)
3551{
3552 struct stream_in *in = (struct stream_in *)stream;
3553 struct audio_device *adev = in->dev;
3554
3555 int ret = -ENOSYS;
3556 ALOGV("%s", __func__);
3557 pthread_mutex_lock(&adev->lock);
3558 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3559 in->capture_started && in->pcm != NULL) {
3560 pcm_stop(in->pcm);
3561 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003562 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003563 }
3564 pthread_mutex_unlock(&adev->lock);
3565 return ret;
3566}
3567
3568static int in_start(const struct audio_stream_in* stream)
3569{
3570 struct stream_in *in = (struct stream_in *)stream;
3571 struct audio_device *adev = in->dev;
3572 int ret = -ENOSYS;
3573
3574 ALOGV("%s in %p", __func__, in);
3575 pthread_mutex_lock(&adev->lock);
3576 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3577 !in->capture_started && in->pcm != NULL) {
3578 if (!in->capture_started) {
3579 ret = start_input_stream(in);
3580 if (ret == 0) {
3581 in->capture_started = true;
3582 }
3583 }
3584 }
3585 pthread_mutex_unlock(&adev->lock);
3586 return ret;
3587}
3588
3589static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3590 int32_t min_size_frames,
3591 struct audio_mmap_buffer_info *info)
3592{
3593 struct stream_in *in = (struct stream_in *)stream;
3594 struct audio_device *adev = in->dev;
3595 int ret = 0;
3596 unsigned int offset1;
3597 unsigned int frames1;
3598 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003599 uint32_t mmap_size;
3600 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003601
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003602 lock_input_stream(in);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003603 pthread_mutex_lock(&adev->lock);
3604 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003605
Eric Laurent0e46adf2016-12-16 12:49:24 -08003606 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003607 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003608 ret = -EINVAL;
3609 goto exit;
3610 }
3611 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003612 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003613 ALOGV("%s in %p", __func__, in);
3614 ret = -ENOSYS;
3615 goto exit;
3616 }
3617 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3618 if (in->pcm_device_id < 0) {
3619 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3620 __func__, in->pcm_device_id, in->usecase);
3621 ret = -EINVAL;
3622 goto exit;
3623 }
Phil Burkbc991042017-02-24 08:06:44 -08003624
3625 adjust_mmap_period_count(&in->config, min_size_frames);
3626
Eric Laurent0e46adf2016-12-16 12:49:24 -08003627 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3628 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3629 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3630 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3631 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3632 step = "open";
3633 ret = -ENODEV;
3634 goto exit;
3635 }
3636
3637 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3638 if (ret < 0) {
3639 step = "begin";
3640 goto exit;
3641 }
3642 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003643 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003644 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003645 ret = platform_get_mmap_data_fd(adev->platform,
3646 in->pcm_device_id, 1 /*capture*/,
3647 &info->shared_memory_fd,
3648 &mmap_size);
3649 if (ret < 0) {
3650 // Fall back to non exclusive mode
3651 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3652 } else {
3653 if (mmap_size < buffer_size) {
3654 step = "mmap";
3655 goto exit;
3656 }
3657 // FIXME: indicate exclusive mode support by returning a negative buffer size
3658 info->buffer_size_frames *= -1;
3659 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003660
Haynes Mathew George96483a22017-03-28 14:52:47 -07003661 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003662
3663 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3664 if (ret < 0) {
3665 step = "commit";
3666 goto exit;
3667 }
3668
Phil Burkbc991042017-02-24 08:06:44 -08003669 in->standby = false;
3670 ret = 0;
3671
Eric Laurent0e46adf2016-12-16 12:49:24 -08003672 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3673 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003674
3675exit:
3676 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003677 if (in->pcm == NULL) {
3678 ALOGE("%s: %s - %d", __func__, step, ret);
3679 } else {
3680 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003681 pcm_close(in->pcm);
3682 in->pcm = NULL;
3683 }
3684 }
3685 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003686 pthread_mutex_unlock(&in->lock);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003687 return ret;
3688}
3689
3690static int in_get_mmap_position(const struct audio_stream_in *stream,
3691 struct audio_mmap_position *position)
3692{
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003693 int ret = 0;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003694 struct stream_in *in = (struct stream_in *)stream;
3695 ALOGVV("%s", __func__);
3696 if (position == NULL) {
3697 return -EINVAL;
3698 }
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003699 lock_input_stream(in);
3700 if (in->usecase != USECASE_AUDIO_RECORD_MMAP ||
3701 in->pcm == NULL) {
3702 ret = -ENOSYS;
3703 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003704 }
3705 struct timespec ts = { 0, 0 };
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003706 ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003707 if (ret < 0) {
3708 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003709 goto exit;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003710 }
Andy Hungfc044e12017-03-20 09:24:22 -07003711 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Haynes Mathew Georgef1aaf362017-12-18 15:10:10 -08003712exit:
3713 pthread_mutex_unlock(&in->lock);
3714 return ret;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003715}
3716
3717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003718static int adev_open_output_stream(struct audio_hw_device *dev,
3719 audio_io_handle_t handle,
3720 audio_devices_t devices,
3721 audio_output_flags_t flags,
3722 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003723 struct audio_stream_out **stream_out,
3724 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725{
3726 struct audio_device *adev = (struct audio_device *)dev;
3727 struct stream_out *out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003728 int i, ret = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003729 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3730 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3731 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732
Andy Hungd9653bd2017-08-01 19:31:39 -07003733 if (is_usb_dev && !is_usb_ready(adev, true /* is_playback */)) {
3734 return -ENOSYS;
3735 }
3736
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003737 ALOGV("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
3738 __func__, config->format, config->sample_rate, config->channel_mask, devices, flags);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739 *stream_out = NULL;
3740 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3741
3742 if (devices == AUDIO_DEVICE_NONE)
3743 devices = AUDIO_DEVICE_OUT_SPEAKER;
3744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 out->flags = flags;
3746 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003747 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003748 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003749 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750
3751 /* Init use case and pcm_config */
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003752 if ((is_hdmi || is_usb_dev) &&
3753 (audio_is_linear_pcm(config->format) || config->format == AUDIO_FORMAT_DEFAULT) &&
3754 (flags == AUDIO_OUTPUT_FLAG_NONE ||
3755 (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003756 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003757 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003758 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003759 if (config->sample_rate == 0)
3760 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3761 if (config->channel_mask == 0)
3762 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3763 if (config->format == AUDIO_FORMAT_DEFAULT)
3764 config->format = AUDIO_FORMAT_PCM_16_BIT;
3765 } else if (is_usb_dev) {
3766 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3767 &config->format,
3768 &out->supported_formats[0],
3769 MAX_SUPPORTED_FORMATS,
3770 &config->channel_mask,
3771 &out->supported_channel_masks[0],
3772 MAX_SUPPORTED_CHANNEL_MASKS,
3773 &config->sample_rate,
3774 &out->supported_sample_rates[0],
3775 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003776 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003777 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003778 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003779 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003780 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003781
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003782
Haynes Mathew George569b7482017-05-08 14:44:27 -07003783 out->sample_rate = config->sample_rate;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003784 out->channel_mask = config->channel_mask;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003785 out->format = config->format;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003786 if (is_hdmi) {
3787 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3788 out->config = pcm_config_hdmi_multi;
3789 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3790 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3791 out->config = pcm_config_mmap_playback;
3792 out->stream.start = out_start;
3793 out->stream.stop = out_stop;
3794 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3795 out->stream.get_mmap_position = out_get_mmap_position;
3796 } else {
3797 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3798 out->config = pcm_config_hifi;
3799 }
3800
3801 out->config.rate = out->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003802 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003803 if (is_hdmi) {
3804 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
3805 audio_bytes_per_sample(out->format));
3806 }
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003807 out->config.format = pcm_format_from_audio_format(out->format);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003808 } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003809 pthread_mutex_lock(&adev->lock);
3810 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3811 pthread_mutex_unlock(&adev->lock);
3812
3813 // reject offload during card offline to allow
3814 // fallback to s/w paths
3815 if (offline) {
3816 ret = -ENODEV;
3817 goto error_open;
3818 }
3819
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003820 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3821 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3822 ALOGE("%s: Unsupported Offload information", __func__);
3823 ret = -EINVAL;
3824 goto error_open;
3825 }
3826 if (!is_supported_format(config->offload_info.format)) {
3827 ALOGE("%s: Unsupported audio format", __func__);
3828 ret = -EINVAL;
3829 goto error_open;
3830 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003831 out->sample_rate = config->offload_info.sample_rate;
3832 if (config->offload_info.channel_mask != AUDIO_CHANNEL_NONE)
3833 out->channel_mask = config->offload_info.channel_mask;
3834 else if (config->channel_mask != AUDIO_CHANNEL_NONE)
3835 out->channel_mask = config->channel_mask;
3836 else
3837 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3838
3839 out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003840
3841 out->compr_config.codec = (struct snd_codec *)
3842 calloc(1, sizeof(struct snd_codec));
3843
3844 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003845
3846 out->stream.set_callback = out_set_callback;
3847 out->stream.pause = out_pause;
3848 out->stream.resume = out_resume;
3849 out->stream.drain = out_drain;
3850 out->stream.flush = out_flush;
3851
3852 out->compr_config.codec->id =
3853 get_snd_codec_id(config->offload_info.format);
3854 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3855 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003856 out->compr_config.codec->sample_rate = out->sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003857 out->compr_config.codec->bit_rate =
3858 config->offload_info.bit_rate;
3859 out->compr_config.codec->ch_in =
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003860 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003861 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3862
3863 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3864 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003865
3866 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003867 create_offload_callback_thread(out);
3868 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3869 __func__, config->offload_info.version,
3870 config->offload_info.bit_rate);
Nadav Bar3d72cfc2018-01-07 12:19:24 +02003871 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3872 switch (config->sample_rate) {
3873 case 0:
3874 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3875 break;
3876 case 8000:
3877 case 16000:
3878 case 48000:
3879 out->sample_rate = config->sample_rate;
3880 break;
3881 default:
3882 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
3883 config->sample_rate);
3884 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3885 ret = -EINVAL;
3886 goto error_open;
3887 }
3888 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3889 switch (config->channel_mask) {
3890 case AUDIO_CHANNEL_NONE:
3891 case AUDIO_CHANNEL_OUT_STEREO:
3892 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3893 break;
3894 default:
3895 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
3896 config->channel_mask);
3897 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3898 ret = -EINVAL;
3899 goto error_open;
3900 }
3901 switch (config->format) {
3902 case AUDIO_FORMAT_DEFAULT:
3903 case AUDIO_FORMAT_PCM_16_BIT:
3904 out->format = AUDIO_FORMAT_PCM_16_BIT;
3905 break;
3906 default:
3907 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
3908 config->format);
3909 config->format = AUDIO_FORMAT_PCM_16_BIT;
3910 ret = -EINVAL;
3911 goto error_open;
3912 }
3913
3914 voice_extn_check_and_set_incall_music_usecase(adev, out);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003915 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003916 switch (config->sample_rate) {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003917 case 0:
3918 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
3919 break;
Kevin Rocard50eff892017-05-02 16:52:05 -07003920 case 8000:
3921 case 16000:
3922 case 48000:
3923 out->sample_rate = config->sample_rate;
3924 break;
3925 default:
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003926 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
3927 config->sample_rate);
3928 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3929 ret = -EINVAL;
3930 break;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003931 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003932 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
3933 switch (config->channel_mask) {
3934 case AUDIO_CHANNEL_NONE:
3935 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3936 break;
3937 case AUDIO_CHANNEL_OUT_STEREO:
3938 out->channel_mask = config->channel_mask;
3939 break;
3940 default:
3941 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
3942 config->channel_mask);
3943 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3944 ret = -EINVAL;
3945 break;
3946 }
3947 switch (config->format) {
3948 case AUDIO_FORMAT_DEFAULT:
3949 out->format = AUDIO_FORMAT_PCM_16_BIT;
3950 break;
3951 case AUDIO_FORMAT_PCM_16_BIT:
3952 out->format = config->format;
3953 break;
3954 default:
3955 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
3956 config->format);
3957 config->format = AUDIO_FORMAT_PCM_16_BIT;
3958 ret = -EINVAL;
3959 break;
3960 }
3961 if (ret != 0)
3962 goto error_open;
3963
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003964 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3965 out->config = pcm_config_afe_proxy_playback;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003966 out->config.rate = out->sample_rate;
3967 out->config.channels =
3968 audio_channel_count_from_out_mask(out->channel_mask);
3969 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003970 adev->voice_tx_output = out;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003971 } else if (flags == AUDIO_OUTPUT_FLAG_VOIP_RX) {
3972 switch (config->sample_rate) {
3973 case 0:
3974 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3975 break;
3976 case 8000:
3977 case 16000:
3978 case 32000:
3979 case 48000:
3980 out->sample_rate = config->sample_rate;
3981 break;
3982 default:
3983 ALOGE("%s: Unsupported sampling rate %d for Voip RX", __func__,
3984 config->sample_rate);
3985 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3986 ret = -EINVAL;
3987 break;
3988 }
Eric Laurentad2dde92017-09-20 18:27:31 -07003989 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
Eric Laurent0dedc2e2017-08-27 14:35:46 -07003990 switch (config->channel_mask) {
3991 case AUDIO_CHANNEL_NONE:
3992 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3993 break;
3994 case AUDIO_CHANNEL_OUT_STEREO:
3995 out->channel_mask = config->channel_mask;
3996 break;
3997 default:
3998 ALOGE("%s: Unsupported channel mask %#x for Voip RX", __func__,
3999 config->channel_mask);
4000 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
4001 ret = -EINVAL;
4002 break;
4003 }
4004 switch (config->format) {
4005 case AUDIO_FORMAT_DEFAULT:
4006 out->format = AUDIO_FORMAT_PCM_16_BIT;
4007 break;
4008 case AUDIO_FORMAT_PCM_16_BIT:
4009 out->format = config->format;
4010 break;
4011 default:
4012 ALOGE("%s: Unsupported format %#x for Voip RX", __func__,
4013 config->format);
4014 config->format = AUDIO_FORMAT_PCM_16_BIT;
4015 ret = -EINVAL;
4016 break;
4017 }
4018 if (ret != 0)
4019 goto error_open;
4020
vivek mehtaa68fea62017-06-08 19:04:02 -07004021 uint32_t buffer_size, frame_size;
vivek mehtaa68fea62017-06-08 19:04:02 -07004022 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
4023 out->config = pcm_config_voip;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004024 out->config.rate = out->sample_rate;
4025 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehtaa68fea62017-06-08 19:04:02 -07004026 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004027 out->sample_rate,
4028 out->format,
vivek mehtaa68fea62017-06-08 19:04:02 -07004029 out->config.channels,
4030 false /*is_low_latency*/);
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004031 frame_size = audio_bytes_per_sample(out->format) * out->config.channels;
vivek mehtaa68fea62017-06-08 19:04:02 -07004032 out->config.period_size = buffer_size / frame_size;
4033 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
4034 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035 } else {
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004036 if (flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
Andy Hung6fcba9c2014-03-18 11:53:32 -07004037 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
4038 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004039 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07004040 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
4041 out->config = pcm_config_deep_buffer;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004042 } else if (flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07004043 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004044 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004045 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004046 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08004047 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
4048 out->config = pcm_config_mmap_playback;
4049 out->stream.start = out_start;
4050 out->stream.stop = out_stop;
4051 out->stream.create_mmap_buffer = out_create_mmap_buffer;
4052 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004053 } else {
4054 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
4055 out->config = pcm_config_low_latency;
4056 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004057
4058 if (config->sample_rate == 0) {
4059 out->sample_rate = out->config.rate;
4060 } else {
4061 out->sample_rate = config->sample_rate;
Andy Hung6fcba9c2014-03-18 11:53:32 -07004062 }
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004063 if (config->channel_mask == AUDIO_CHANNEL_NONE) {
4064 out->channel_mask = audio_channel_out_mask_from_count(out->config.channels);
4065 } else {
4066 out->channel_mask = config->channel_mask;
4067 }
4068 if (config->format == AUDIO_FORMAT_DEFAULT)
4069 out->format = audio_format_from_pcm_format(out->config.format);
4070 else if (!audio_is_linear_pcm(config->format)) {
4071 config->format = AUDIO_FORMAT_PCM_16_BIT;
4072 ret = -EINVAL;
4073 goto error_open;
4074 } else {
4075 out->format = config->format;
4076 }
4077
4078 out->config.rate = out->sample_rate;
4079 out->config.channels =
4080 audio_channel_count_from_out_mask(out->channel_mask);
4081 if (out->format != audio_format_from_pcm_format(out->config.format)) {
4082 out->config.format = pcm_format_from_audio_format(out->format);
4083 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084 }
Kevin Rocard50eff892017-05-02 16:52:05 -07004085
4086 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
4087 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
Eric Laurent0dedc2e2017-08-27 14:35:46 -07004088 (config->channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != out->channel_mask)) {
Kevin Rocard50eff892017-05-02 16:52:05 -07004089 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
4090 __func__, config->sample_rate, config->format, config->channel_mask);
4091 config->sample_rate = out->sample_rate;
4092 config->format = out->format;
4093 config->channel_mask = out->channel_mask;
4094 ret = -EINVAL;
4095 goto error_open;
4096 }
4097
Andy Hung6fcba9c2014-03-18 11:53:32 -07004098 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
4099 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004101 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004102 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004103 adev->primary_output = out;
4104 else {
4105 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004106 ret = -EEXIST;
4107 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004108 }
4109 }
4110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111 /* Check if this usecase is already existing */
4112 pthread_mutex_lock(&adev->lock);
4113 if (get_usecase_from_list(adev, out->usecase) != NULL) {
4114 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004115 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004116 ret = -EEXIST;
4117 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118 }
4119 pthread_mutex_unlock(&adev->lock);
4120
4121 out->stream.common.get_sample_rate = out_get_sample_rate;
4122 out->stream.common.set_sample_rate = out_set_sample_rate;
4123 out->stream.common.get_buffer_size = out_get_buffer_size;
4124 out->stream.common.get_channels = out_get_channels;
4125 out->stream.common.get_format = out_get_format;
4126 out->stream.common.set_format = out_set_format;
4127 out->stream.common.standby = out_standby;
4128 out->stream.common.dump = out_dump;
4129 out->stream.common.set_parameters = out_set_parameters;
4130 out->stream.common.get_parameters = out_get_parameters;
4131 out->stream.common.add_audio_effect = out_add_audio_effect;
4132 out->stream.common.remove_audio_effect = out_remove_audio_effect;
4133 out->stream.get_latency = out_get_latency;
4134 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004135#ifdef NO_AUDIO_OUT
4136 out->stream.write = out_write_for_no_output;
4137#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07004139#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 out->stream.get_render_position = out_get_render_position;
4141 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004142 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143
Eric Laurent0e46adf2016-12-16 12:49:24 -08004144 if (out->realtime)
4145 out->af_period_multiplier = af_period_multiplier;
4146 else
4147 out->af_period_multiplier = 1;
4148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004149 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07004150 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07004151 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004152
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004153 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004154 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004155 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
4156
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157 config->format = out->stream.common.get_format(&out->stream.common);
4158 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
4159 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
4160
Andy Hunga452b0a2017-03-15 14:51:15 -07004161 out->error_log = error_log_create(
4162 ERROR_LOG_ENTRIES,
4163 1000000000 /* aggregate consecutive identical errors within one second in ns */);
4164
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004165 /*
4166 By locking output stream before registering, we allow the callback
4167 to update stream's state only after stream's initial state is set to
4168 adev state.
4169 */
4170 lock_output_stream(out);
4171 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
4172 pthread_mutex_lock(&adev->lock);
4173 out->card_status = adev->card_status;
4174 pthread_mutex_unlock(&adev->lock);
4175 pthread_mutex_unlock(&out->lock);
4176
vivek mehta4a824772017-06-08 19:05:49 -07004177 stream_app_type_cfg_init(&out->app_type_cfg);
4178
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004179 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004180
Eric Laurent994a6932013-07-17 11:51:42 -07004181 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004183
4184error_open:
4185 free(out);
4186 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07004187 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07004188 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004189}
4190
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004191static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004192 struct audio_stream_out *stream)
4193{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004194 struct stream_out *out = (struct stream_out *)stream;
4195 struct audio_device *adev = out->dev;
4196
Eric Laurent994a6932013-07-17 11:51:42 -07004197 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004198
4199 // must deregister from sndmonitor first to prevent races
4200 // between the callback and close_stream
4201 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004202 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004203 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
4204 destroy_offload_callback_thread(out);
4205
4206 if (out->compr_config.codec != NULL)
4207 free(out->compr_config.codec);
4208 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07004209
4210 if (adev->voice_tx_output == out)
4211 adev->voice_tx_output = NULL;
4212
Andy Hunga452b0a2017-03-15 14:51:15 -07004213 error_log_destroy(out->error_log);
4214 out->error_log = NULL;
4215
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004216 pthread_cond_destroy(&out->cond);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004217 pthread_mutex_destroy(&out->pre_lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004218 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004219 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07004220 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004221}
4222
4223static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
4224{
4225 struct audio_device *adev = (struct audio_device *)dev;
4226 struct str_parms *parms;
4227 char *str;
4228 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004229 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004230 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07004231 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232
Joe Onorato188b6222016-03-01 11:02:27 -08004233 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004234
4235 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004236
4237 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004238 status = voice_set_parameters(adev, parms);
4239 if (status != 0) {
4240 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004241 }
4242
4243 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
4244 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07004245 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004246 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4247 adev->bluetooth_nrec = true;
4248 else
4249 adev->bluetooth_nrec = false;
4250 }
4251
4252 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
4253 if (ret >= 0) {
4254 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
4255 adev->screen_off = false;
4256 else
4257 adev->screen_off = true;
4258 }
4259
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004260 ret = str_parms_get_int(parms, "rotation", &val);
4261 if (ret >= 0) {
4262 bool reverse_speakers = false;
4263 switch(val) {
4264 // FIXME: note that the code below assumes that the speakers are in the correct placement
4265 // relative to the user when the device is rotated 90deg from its default rotation. This
4266 // assumption is device-specific, not platform-specific like this code.
4267 case 270:
4268 reverse_speakers = true;
4269 break;
4270 case 0:
4271 case 90:
4272 case 180:
4273 break;
4274 default:
4275 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07004276 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004277 }
Eric Laurent03f09432014-03-25 18:09:11 -07004278 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07004279 // check and set swap
4280 // - check if orientation changed and speaker active
4281 // - set rotation and cache the rotation value
4282 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004283 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07004284 }
4285
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004286 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
4287 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004288 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004289 }
4290
David Linee3fe402017-03-13 10:00:42 -07004291 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
4292 if (ret >= 0) {
4293 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004294 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004295 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4296 if (ret >= 0) {
4297 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004298 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004299 }
Eric Laurent99dab492017-06-17 15:19:08 -07004300 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004301 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4302 if (ret >= 0) {
4303 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004304 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004305 }
4306 }
4307 }
4308
4309 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
4310 if (ret >= 0) {
4311 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07004312 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004313 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4314 if (ret >= 0) {
4315 const int card = atoi(value);
4316
Eric Laurent99dab492017-06-17 15:19:08 -07004317 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004318 }
Eric Laurent99dab492017-06-17 15:19:08 -07004319 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07004320 ret = str_parms_get_str(parms, "card", value, sizeof(value));
4321 if (ret >= 0) {
4322 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07004323 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07004324 }
4325 }
4326 }
4327
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08004328 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004329done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004330 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004331 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07004332 ALOGV("%s: exit with code(%d)", __func__, status);
4333 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004334}
4335
4336static char* adev_get_parameters(const struct audio_hw_device *dev,
4337 const char *keys)
4338{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004339 struct audio_device *adev = (struct audio_device *)dev;
4340 struct str_parms *reply = str_parms_create();
4341 struct str_parms *query = str_parms_create_str(keys);
4342 char *str;
4343
4344 pthread_mutex_lock(&adev->lock);
4345
4346 voice_get_parameters(adev, query, reply);
4347 str = str_parms_to_str(reply);
4348 str_parms_destroy(query);
4349 str_parms_destroy(reply);
4350
4351 pthread_mutex_unlock(&adev->lock);
4352 ALOGV("%s: exit: returns - %s", __func__, str);
4353 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354}
4355
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004356static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357{
4358 return 0;
4359}
4360
Haynes Mathew George5191a852013-09-11 14:19:36 -07004361static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4362{
4363 int ret;
4364 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004365
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004366 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4367
Haynes Mathew George5191a852013-09-11 14:19:36 -07004368 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004369 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004370 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004371
Haynes Mathew George5191a852013-09-11 14:19:36 -07004372 return ret;
4373}
4374
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004375static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004376{
4377 return -ENOSYS;
4378}
4379
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004380static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4381 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382{
4383 return -ENOSYS;
4384}
4385
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004386static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387{
4388 return -ENOSYS;
4389}
4390
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004391static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004392{
4393 return -ENOSYS;
4394}
4395
4396static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4397{
4398 struct audio_device *adev = (struct audio_device *)dev;
4399
4400 pthread_mutex_lock(&adev->lock);
4401 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004402 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004403 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004404 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4405 voice_is_in_call(adev)) {
4406 voice_stop_call(adev);
4407 adev->current_call_output = NULL;
4408 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004409 }
4410 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004411
4412 audio_extn_extspk_set_mode(adev->extspk, mode);
4413
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004414 return 0;
4415}
4416
4417static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4418{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004419 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004421
Eric Laurent2bafff12016-03-17 12:17:23 -07004422 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004423 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004424 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4425 ret = audio_extn_hfp_set_mic_mute(adev, state);
4426 } else {
4427 ret = voice_set_mic_mute(adev, state);
4428 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004429 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004430 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004431
4432 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004433}
4434
4435static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4436{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004437 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004438 return 0;
4439}
4440
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004441static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004442 const struct audio_config *config)
4443{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004444 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004445
Eric Laurent74b55762017-07-09 17:04:53 -07004446 /* Don't know if USB HIFI in this context so use true to be conservative */
4447 if (check_input_parameters(config->sample_rate, config->format, channel_count,
4448 true /*is_usb_hifi */) != 0)
4449 return 0;
4450
vivek mehtaa68fea62017-06-08 19:04:02 -07004451 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4452 config->sample_rate, config->format,
4453 channel_count,
4454 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004455}
4456
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004457static bool adev_input_allow_hifi_record(struct audio_device *adev,
4458 audio_devices_t devices,
4459 audio_input_flags_t flags,
4460 audio_source_t source) {
4461 const bool allowed = true;
4462
4463 if (!audio_is_usb_in_device(devices))
4464 return !allowed;
4465
4466 switch (flags) {
4467 case AUDIO_INPUT_FLAG_NONE:
4468 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4469 break;
4470 default:
4471 return !allowed;
4472 }
4473
4474 switch (source) {
4475 case AUDIO_SOURCE_DEFAULT:
4476 case AUDIO_SOURCE_MIC:
4477 case AUDIO_SOURCE_UNPROCESSED:
4478 break;
4479 default:
4480 return !allowed;
4481 }
4482
4483 switch (adev->mode) {
4484 case 0:
4485 break;
4486 default:
4487 return !allowed;
4488 }
4489
4490 return allowed;
4491}
4492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004493static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004494 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495 audio_devices_t devices,
4496 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004497 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004498 audio_input_flags_t flags,
4499 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004500 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004501{
4502 struct audio_device *adev = (struct audio_device *)dev;
4503 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004504 int ret = 0, buffer_size, frame_size;
Eric Laurent74b55762017-07-09 17:04:53 -07004505 int channel_count;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004506 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004507 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004508 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4509 devices,
4510 flags,
4511 source);
Eric Laurent74b55762017-07-09 17:04:53 -07004512 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004513 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004514
Andy Hungd9653bd2017-08-01 19:31:39 -07004515 if (is_usb_dev && !is_usb_ready(adev, false /* is_playback */)) {
4516 return -ENOSYS;
4517 }
4518
Eric Laurent74b55762017-07-09 17:04:53 -07004519 if (!(is_usb_dev && may_use_hifi_record)) {
4520 if (config->sample_rate == 0)
4521 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4522 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4523 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4524 if (config->format == AUDIO_FORMAT_DEFAULT)
4525 config->format = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004526
Eric Laurent74b55762017-07-09 17:04:53 -07004527 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
4528
4529 if (check_input_parameters(config->sample_rate, config->format, channel_count, false) != 0)
4530 return -EINVAL;
4531 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004533 if (audio_extn_tfa_98xx_is_supported() &&
4534 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004535 return -EINVAL;
4536
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004537 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4538
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004539 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004540 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004541
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542 in->stream.common.get_sample_rate = in_get_sample_rate;
4543 in->stream.common.set_sample_rate = in_set_sample_rate;
4544 in->stream.common.get_buffer_size = in_get_buffer_size;
4545 in->stream.common.get_channels = in_get_channels;
4546 in->stream.common.get_format = in_get_format;
4547 in->stream.common.set_format = in_set_format;
4548 in->stream.common.standby = in_standby;
4549 in->stream.common.dump = in_dump;
4550 in->stream.common.set_parameters = in_set_parameters;
4551 in->stream.common.get_parameters = in_get_parameters;
4552 in->stream.common.add_audio_effect = in_add_audio_effect;
4553 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4554 in->stream.set_gain = in_set_gain;
4555 in->stream.read = in_read;
4556 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004557 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004558
4559 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004560 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562 in->standby = 1;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004563 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004564 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004565
Haynes Mathew George569b7482017-05-08 14:44:27 -07004566 if (is_usb_dev && may_use_hifi_record) {
4567 /* HiFi record selects an appropriate format, channel, rate combo
4568 depending on sink capabilities*/
4569 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4570 &config->format,
4571 &in->supported_formats[0],
4572 MAX_SUPPORTED_FORMATS,
4573 &config->channel_mask,
4574 &in->supported_channel_masks[0],
4575 MAX_SUPPORTED_CHANNEL_MASKS,
4576 &config->sample_rate,
4577 &in->supported_sample_rates[0],
4578 MAX_SUPPORTED_SAMPLE_RATES);
4579 if (ret != 0) {
4580 ret = -EINVAL;
4581 goto err_open;
4582 }
Eric Laurent74b55762017-07-09 17:04:53 -07004583 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004584 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004585 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004586 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4587 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4588 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4589 bool ret_error = false;
4590 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4591 from HAL is 8_24
4592 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4593 8_24 return error indicating supported format is 8_24
4594 *> In case of any other source requesting 24 bit or float return error
4595 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004596
vivek mehta57ff9b52016-04-28 14:13:08 -07004597 on error flinger will retry with supported format passed
4598 */
4599 if (source != AUDIO_SOURCE_UNPROCESSED) {
4600 config->format = AUDIO_FORMAT_PCM_16_BIT;
4601 ret_error = true;
4602 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4603 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4604 ret_error = true;
4605 }
4606
4607 if (ret_error) {
4608 ret = -EINVAL;
4609 goto err_open;
4610 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004611 }
4612
vivek mehta57ff9b52016-04-28 14:13:08 -07004613 in->format = config->format;
Eric Laurent74b55762017-07-09 17:04:53 -07004614 in->channel_mask = config->channel_mask;
vivek mehta57ff9b52016-04-28 14:13:08 -07004615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004616 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004617 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4618 if (config->sample_rate == 0)
4619 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4620 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4621 config->sample_rate != 8000) {
4622 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4623 ret = -EINVAL;
4624 goto err_open;
4625 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004626
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004627 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4628 config->format = AUDIO_FORMAT_PCM_16_BIT;
4629 ret = -EINVAL;
4630 goto err_open;
4631 }
4632
4633 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4634 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004635 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004636 } else if (is_usb_dev && may_use_hifi_record) {
4637 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4638 in->config = pcm_config_audio_capture;
4639 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004640 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4641 config->sample_rate,
4642 config->format,
4643 channel_count,
4644 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004645 in->config.period_size = buffer_size / frame_size;
4646 in->config.rate = config->sample_rate;
4647 in->af_period_multiplier = 1;
4648 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004649 } else {
4650 in->usecase = USECASE_AUDIO_RECORD;
4651 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004652 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004653 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004654#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004655 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004656#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004657 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004658 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004659 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004660 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004661 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4662 config->sample_rate,
4663 config->format,
4664 channel_count,
4665 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004666 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004667 in->config.rate = config->sample_rate;
4668 in->af_period_multiplier = 1;
4669 } else {
4670 // period size is left untouched for rt mode playback
4671 in->config = pcm_config_audio_capture_rt;
4672 in->af_period_multiplier = af_period_multiplier;
4673 }
4674 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4675 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004676 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004677 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4678 in->config = pcm_config_mmap_capture;
4679 in->stream.start = in_start;
4680 in->stream.stop = in_stop;
4681 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4682 in->stream.get_mmap_position = in_get_mmap_position;
4683 in->af_period_multiplier = 1;
4684 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004685 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004686 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004687 (config->sample_rate == 8000 ||
4688 config->sample_rate == 16000 ||
4689 config->sample_rate == 32000 ||
4690 config->sample_rate == 48000) &&
4691 channel_count == 1) {
4692 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4693 in->config = pcm_config_audio_capture;
4694 frame_size = audio_stream_in_frame_size(&in->stream);
4695 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4696 config->sample_rate,
4697 config->format,
4698 channel_count, false /*is_low_latency*/);
4699 in->config.period_size = buffer_size / frame_size;
4700 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4701 in->config.rate = config->sample_rate;
4702 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004703 } else {
4704 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004705 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004706 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4707 config->sample_rate,
4708 config->format,
4709 channel_count,
4710 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004711 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004712 in->config.rate = config->sample_rate;
4713 in->af_period_multiplier = 1;
4714 }
4715 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4716 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004717 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004718
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004719 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004720 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004721
Andy Hungd13f0d32017-06-12 13:58:37 -07004722 in->error_log = error_log_create(
4723 ERROR_LOG_ENTRIES,
4724 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4725
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004726 /* This stream could be for sound trigger lab,
4727 get sound trigger pcm if present */
4728 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004729
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004730 lock_input_stream(in);
4731 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4732 pthread_mutex_lock(&adev->lock);
4733 in->card_status = adev->card_status;
4734 pthread_mutex_unlock(&adev->lock);
4735 pthread_mutex_unlock(&in->lock);
4736
vivek mehta4a824772017-06-08 19:05:49 -07004737 stream_app_type_cfg_init(&in->app_type_cfg);
4738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004739 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004740 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004741 return 0;
4742
4743err_open:
4744 free(in);
4745 *stream_in = NULL;
4746 return ret;
4747}
4748
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004749static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004750 struct audio_stream_in *stream)
4751{
Andy Hungd13f0d32017-06-12 13:58:37 -07004752 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004753 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004754
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004755 // must deregister from sndmonitor first to prevent races
4756 // between the callback and close_stream
4757 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004759
4760 error_log_destroy(in->error_log);
4761 in->error_log = NULL;
4762
Andy Hung0dbb52b2017-08-09 13:51:38 -07004763 pthread_mutex_destroy(&in->pre_lock);
4764 pthread_mutex_destroy(&in->lock);
4765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004766 free(stream);
4767
4768 return;
4769}
4770
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004771static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004772{
4773 return 0;
4774}
4775
Andy Hung31aca912014-03-20 17:14:59 -07004776/* verifies input and output devices and their capabilities.
4777 *
4778 * This verification is required when enabling extended bit-depth or
4779 * sampling rates, as not all qcom products support it.
4780 *
4781 * Suitable for calling only on initialization such as adev_open().
4782 * It fills the audio_device use_case_table[] array.
4783 *
4784 * Has a side-effect that it needs to configure audio routing / devices
4785 * in order to power up the devices and read the device parameters.
4786 * It does not acquire any hw device lock. Should restore the devices
4787 * back to "normal state" upon completion.
4788 */
4789static int adev_verify_devices(struct audio_device *adev)
4790{
4791 /* enumeration is a bit difficult because one really wants to pull
4792 * the use_case, device id, etc from the hidden pcm_device_table[].
4793 * In this case there are the following use cases and device ids.
4794 *
4795 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4796 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004797 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004798 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4799 * [USECASE_AUDIO_RECORD] = {0, 0},
4800 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4801 * [USECASE_VOICE_CALL] = {2, 2},
4802 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004803 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004804 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4805 */
4806
4807 /* should be the usecases enabled in adev_open_input_stream() */
4808 static const int test_in_usecases[] = {
4809 USECASE_AUDIO_RECORD,
4810 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4811 };
4812 /* should be the usecases enabled in adev_open_output_stream()*/
4813 static const int test_out_usecases[] = {
4814 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4815 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4816 };
4817 static const usecase_type_t usecase_type_by_dir[] = {
4818 PCM_PLAYBACK,
4819 PCM_CAPTURE,
4820 };
4821 static const unsigned flags_by_dir[] = {
4822 PCM_OUT,
4823 PCM_IN,
4824 };
4825
4826 size_t i;
4827 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004828 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004829 char info[512]; /* for possible debug info */
4830
4831 for (dir = 0; dir < 2; ++dir) {
4832 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4833 const unsigned flags_dir = flags_by_dir[dir];
4834 const size_t testsize =
4835 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4836 const int *testcases =
4837 dir ? test_in_usecases : test_out_usecases;
4838 const audio_devices_t audio_device =
4839 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4840
4841 for (i = 0; i < testsize; ++i) {
4842 const audio_usecase_t audio_usecase = testcases[i];
4843 int device_id;
4844 snd_device_t snd_device;
4845 struct pcm_params **pparams;
4846 struct stream_out out;
4847 struct stream_in in;
4848 struct audio_usecase uc_info;
4849 int retval;
4850
4851 pparams = &adev->use_case_table[audio_usecase];
4852 pcm_params_free(*pparams); /* can accept null input */
4853 *pparams = NULL;
4854
4855 /* find the device ID for the use case (signed, for error) */
4856 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4857 if (device_id < 0)
4858 continue;
4859
4860 /* prepare structures for device probing */
4861 memset(&uc_info, 0, sizeof(uc_info));
4862 uc_info.id = audio_usecase;
4863 uc_info.type = usecase_type;
4864 if (dir) {
4865 adev->active_input = &in;
4866 memset(&in, 0, sizeof(in));
4867 in.device = audio_device;
4868 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4869 uc_info.stream.in = &in;
4870 } else {
4871 adev->active_input = NULL;
4872 }
4873 memset(&out, 0, sizeof(out));
4874 out.devices = audio_device; /* only field needed in select_devices */
4875 uc_info.stream.out = &out;
4876 uc_info.devices = audio_device;
4877 uc_info.in_snd_device = SND_DEVICE_NONE;
4878 uc_info.out_snd_device = SND_DEVICE_NONE;
4879 list_add_tail(&adev->usecase_list, &uc_info.list);
4880
4881 /* select device - similar to start_(in/out)put_stream() */
4882 retval = select_devices(adev, audio_usecase);
4883 if (retval >= 0) {
4884 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4885#if LOG_NDEBUG == 0
4886 if (*pparams) {
4887 ALOGV("%s: (%s) card %d device %d", __func__,
4888 dir ? "input" : "output", card_id, device_id);
4889 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004890 } else {
4891 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4892 }
4893#endif
4894 }
4895
4896 /* deselect device - similar to stop_(in/out)put_stream() */
4897 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004898 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004899 /* 2. Disable the rx device */
4900 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004901 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004902 list_remove(&uc_info.list);
4903 }
4904 }
4905 adev->active_input = NULL; /* restore adev state */
4906 return 0;
4907}
4908
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004909static int adev_close(hw_device_t *device)
4910{
Andy Hung31aca912014-03-20 17:14:59 -07004911 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004912 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004913
4914 if (!adev)
4915 return 0;
4916
4917 pthread_mutex_lock(&adev_init_lock);
4918
4919 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004920 audio_extn_snd_mon_unregister_listener(adev);
4921 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004922 audio_route_free(adev->audio_route);
4923 free(adev->snd_dev_ref_cnt);
4924 platform_deinit(adev->platform);
4925 audio_extn_extspk_deinit(adev->extspk);
4926 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004927 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004928 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4929 pcm_params_free(adev->use_case_table[i]);
4930 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004931 if (adev->adm_deinit)
4932 adev->adm_deinit(adev->adm_data);
Andy Hung0dbb52b2017-08-09 13:51:38 -07004933 pthread_mutex_destroy(&adev->lock);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004934 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004935 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004936
4937 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004938
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004939 return 0;
4940}
4941
Glenn Kasten4f993392014-05-14 07:30:48 -07004942/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4943 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4944 * just that it _might_ work.
4945 */
4946static int period_size_is_plausible_for_low_latency(int period_size)
4947{
4948 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004949 case 48:
4950 case 96:
4951 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004952 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004953 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004954 case 240:
4955 case 320:
4956 case 480:
4957 return 1;
4958 default:
4959 return 0;
4960 }
4961}
4962
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004963static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4964{
4965 int card;
4966 card_status_t status;
4967
4968 if (!parms)
4969 return;
4970
4971 if (parse_snd_card_status(parms, &card, &status) < 0)
4972 return;
4973
4974 pthread_mutex_lock(&adev->lock);
4975 bool valid_cb = (card == adev->snd_card);
4976 if (valid_cb) {
4977 if (adev->card_status != status) {
4978 adev->card_status = status;
4979 platform_snd_card_update(adev->platform, status);
4980 }
4981 }
4982 pthread_mutex_unlock(&adev->lock);
4983 return;
4984}
4985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004986static int adev_open(const hw_module_t *module, const char *name,
4987 hw_device_t **device)
4988{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004989 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004990
Eric Laurent2bafff12016-03-17 12:17:23 -07004991 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004992 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004993 pthread_mutex_lock(&adev_init_lock);
4994 if (audio_device_ref_count != 0) {
4995 *device = &adev->device.common;
4996 audio_device_ref_count++;
4997 ALOGV("%s: returning existing instance of adev", __func__);
4998 ALOGV("%s: exit", __func__);
4999 pthread_mutex_unlock(&adev_init_lock);
5000 return 0;
5001 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005002 adev = calloc(1, sizeof(struct audio_device));
5003
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005004 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
5005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005006 adev->device.common.tag = HARDWARE_DEVICE_TAG;
5007 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
5008 adev->device.common.module = (struct hw_module_t *)module;
5009 adev->device.common.close = adev_close;
5010
5011 adev->device.init_check = adev_init_check;
5012 adev->device.set_voice_volume = adev_set_voice_volume;
5013 adev->device.set_master_volume = adev_set_master_volume;
5014 adev->device.get_master_volume = adev_get_master_volume;
5015 adev->device.set_master_mute = adev_set_master_mute;
5016 adev->device.get_master_mute = adev_get_master_mute;
5017 adev->device.set_mode = adev_set_mode;
5018 adev->device.set_mic_mute = adev_set_mic_mute;
5019 adev->device.get_mic_mute = adev_get_mic_mute;
5020 adev->device.set_parameters = adev_set_parameters;
5021 adev->device.get_parameters = adev_get_parameters;
5022 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
5023 adev->device.open_output_stream = adev_open_output_stream;
5024 adev->device.close_output_stream = adev_close_output_stream;
5025 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08005026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005027 adev->device.close_input_stream = adev_close_input_stream;
5028 adev->device.dump = adev_dump;
5029
5030 /* Set the default route before the PCM stream is opened */
5031 pthread_mutex_lock(&adev->lock);
5032 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08005033 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08005034 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005035 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08005036 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07005037 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07005038 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07005039 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08005040 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005041 pthread_mutex_unlock(&adev->lock);
5042
5043 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07005044 adev->platform = platform_init(adev);
5045 if (!adev->platform) {
5046 free(adev->snd_dev_ref_cnt);
5047 free(adev);
5048 ALOGE("%s: Failed to init platform data, aborting.", __func__);
5049 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005050 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07005051 return -EINVAL;
5052 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05005053 adev->extspk = audio_extn_extspk_init(adev);
5054
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005055 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
5056 if (adev->visualizer_lib == NULL) {
5057 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
5058 } else {
5059 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
5060 adev->visualizer_start_output =
5061 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5062 "visualizer_hal_start_output");
5063 adev->visualizer_stop_output =
5064 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
5065 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07005066 }
5067
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005068 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
5069 if (adev->offload_effects_lib == NULL) {
5070 ALOGW("%s: DLOPEN failed for %s", __func__,
5071 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5072 } else {
5073 ALOGV("%s: DLOPEN successful for %s", __func__,
5074 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
5075 adev->offload_effects_start_output =
5076 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5077 "offload_effects_bundle_hal_start_output");
5078 adev->offload_effects_stop_output =
5079 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
5080 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07005081 }
5082
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07005083 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
5084 if (adev->adm_lib == NULL) {
5085 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
5086 } else {
5087 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
5088 adev->adm_init = (adm_init_t)
5089 dlsym(adev->adm_lib, "adm_init");
5090 adev->adm_deinit = (adm_deinit_t)
5091 dlsym(adev->adm_lib, "adm_deinit");
5092 adev->adm_register_input_stream = (adm_register_input_stream_t)
5093 dlsym(adev->adm_lib, "adm_register_input_stream");
5094 adev->adm_register_output_stream = (adm_register_output_stream_t)
5095 dlsym(adev->adm_lib, "adm_register_output_stream");
5096 adev->adm_deregister_stream = (adm_deregister_stream_t)
5097 dlsym(adev->adm_lib, "adm_deregister_stream");
5098 adev->adm_request_focus = (adm_request_focus_t)
5099 dlsym(adev->adm_lib, "adm_request_focus");
5100 adev->adm_abandon_focus = (adm_abandon_focus_t)
5101 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08005102 adev->adm_set_config = (adm_set_config_t)
5103 dlsym(adev->adm_lib, "adm_set_config");
5104 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
5105 dlsym(adev->adm_lib, "adm_request_focus_v2");
5106 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
5107 dlsym(adev->adm_lib, "adm_is_noirq_avail");
5108 adev->adm_on_routing_change = (adm_on_routing_change_t)
5109 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005110 }
5111
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005112 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05005113 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07005114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07005116
Andy Hung31aca912014-03-20 17:14:59 -07005117 if (k_enable_extended_precision)
5118 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005119
Glenn Kasten4f993392014-05-14 07:30:48 -07005120 char value[PROPERTY_VALUE_MAX];
5121 int trial;
5122 if (property_get("audio_hal.period_size", value, NULL) > 0) {
5123 trial = atoi(value);
5124 if (period_size_is_plausible_for_low_latency(trial)) {
5125 pcm_config_low_latency.period_size = trial;
5126 pcm_config_low_latency.start_threshold = trial / 4;
5127 pcm_config_low_latency.avail_min = trial / 4;
5128 configured_low_latency_capture_period_size = trial;
5129 }
5130 }
5131 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
5132 trial = atoi(value);
5133 if (period_size_is_plausible_for_low_latency(trial)) {
5134 configured_low_latency_capture_period_size = trial;
5135 }
5136 }
5137
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08005138 // commented as full set of app type cfg is sent from platform
5139 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07005140 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08005141
5142 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
5143 af_period_multiplier = atoi(value);
5144 if (af_period_multiplier < 0) {
5145 af_period_multiplier = 2;
5146 } else if (af_period_multiplier > 4) {
5147 af_period_multiplier = 4;
5148 }
5149 ALOGV("new period_multiplier = %d", af_period_multiplier);
5150 }
5151
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08005152 audio_extn_tfa_98xx_init(adev);
5153
vivek mehta1a9b7c02015-06-25 11:49:38 -07005154 pthread_mutex_unlock(&adev_init_lock);
5155
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07005156 if (adev->adm_init)
5157 adev->adm_data = adev->adm_init();
5158
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005159 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07005160 audio_extn_snd_mon_init();
5161 pthread_mutex_lock(&adev->lock);
5162 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
5163 adev->card_status = CARD_STATUS_ONLINE;
5164 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07005165 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07005166
Eric Laurent2bafff12016-03-17 12:17:23 -07005167 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005168 return 0;
5169}
5170
5171static struct hw_module_methods_t hal_module_methods = {
5172 .open = adev_open,
5173};
5174
5175struct audio_module HAL_MODULE_INFO_SYM = {
5176 .common = {
5177 .tag = HARDWARE_MODULE_TAG,
5178 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
5179 .hal_api_version = HARDWARE_HAL_API_VERSION,
5180 .id = AUDIO_HARDWARE_MODULE_ID,
5181 .name = "QCOM Audio HAL",
5182 .author = "Code Aurora Forum",
5183 .methods = &hal_module_methods,
5184 },
5185};