blob: a0d3a58376d2ad6ba128cf5b371f3ab975d60902 [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
38#include <cutils/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"
Eric Laurentb23d5282013-05-14 15:27:20 -070054#include "platform_api.h"
55#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070056#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080059#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060
Eric Laurent397db572016-05-11 11:31:47 -070061/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
62 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070063#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070064// 2 buffers causes problems with high bitrate files
65#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066/* ToDo: Check and update a proper value in msec */
67#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070068/* treat as unsigned Q1.13 */
69#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070070#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070071
72/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070073#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070074
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070075#define PROXY_OPEN_RETRY_COUNT 100
76#define PROXY_OPEN_WAIT_TIME 20
77
vivek mehtadae44712015-07-27 14:13:18 -070078#define MIN_CHANNEL_COUNT 1
79#define DEFAULT_CHANNEL_COUNT 2
80
Jean-Michel Trivic0750692015-10-12 12:12:32 -070081#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
82#define MAX_CHANNEL_COUNT 1
83#else
vivek mehtadae44712015-07-27 14:13:18 -070084#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
85#define XSTR(x) STR(x)
86#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070087#endif
vivek mehtadae44712015-07-27 14:13:18 -070088
Haynes Mathew George03c40102016-01-29 17:57:48 -080089#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
90
Glenn Kasten4f993392014-05-14 07:30:48 -070091static unsigned int configured_low_latency_capture_period_size =
92 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
93
Eric Laurent0e46adf2016-12-16 12:49:24 -080094
95#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080096#define MMAP_PERIOD_COUNT_MIN 32
97#define MMAP_PERIOD_COUNT_MAX 512
98#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -080099
Andy Hungd13f0d32017-06-12 13:58:37 -0700100static const int64_t NANOS_PER_SECOND = 1000000000;
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",
Eric Laurentb23d5282013-05-14 15:27:20 -0700288};
289
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800290
291#define STRING_TO_ENUM(string) { #string, string }
292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800293struct string_to_enum {
294 const char *name;
295 uint32_t value;
296};
297
Haynes Mathew George569b7482017-05-08 14:44:27 -0700298static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800299 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
300 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
301 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George569b7482017-05-08 14:44:27 -0700302 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
303 //TBD - string values for channel_in > 2?
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800304};
305
Haynes Mathew George5191a852013-09-11 14:19:36 -0700306static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700307static struct audio_device *adev = NULL;
Andy Hung9e737de2017-05-22 10:51:22 -0700308static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700309static unsigned int audio_device_ref_count;
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700310//cache last MBDRC cal step level
311static int last_known_cal_step = -1 ;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700312
Haynes Mathew George03c40102016-01-29 17:57:48 -0800313static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
314 int flags __unused)
315{
316 int dir = 0;
317 switch (uc_id) {
318 case USECASE_AUDIO_RECORD_LOW_LATENCY:
319 dir = 1;
320 case USECASE_AUDIO_PLAYBACK_ULL:
321 break;
322 default:
323 return false;
324 }
325
326 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
327 PCM_PLAYBACK : PCM_CAPTURE);
328 if (adev->adm_is_noirq_avail)
329 return adev->adm_is_noirq_avail(adev->adm_data,
330 adev->snd_card, dev_id, dir);
331 return false;
332}
333
334static void register_out_stream(struct stream_out *out)
335{
336 struct audio_device *adev = out->dev;
337 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
338 return;
339
340 if (!adev->adm_register_output_stream)
341 return;
342
343 adev->adm_register_output_stream(adev->adm_data,
344 out->handle,
345 out->flags);
346
347 if (!adev->adm_set_config)
348 return;
349
350 if (out->realtime) {
351 adev->adm_set_config(adev->adm_data,
352 out->handle,
353 out->pcm, &out->config);
354 }
355}
356
357static void register_in_stream(struct stream_in *in)
358{
359 struct audio_device *adev = in->dev;
360 if (!adev->adm_register_input_stream)
361 return;
362
363 adev->adm_register_input_stream(adev->adm_data,
364 in->capture_handle,
365 in->flags);
366
367 if (!adev->adm_set_config)
368 return;
369
370 if (in->realtime) {
371 adev->adm_set_config(adev->adm_data,
372 in->capture_handle,
373 in->pcm,
374 &in->config);
375 }
376}
377
378static void request_out_focus(struct stream_out *out, long ns)
379{
380 struct audio_device *adev = out->dev;
381
Haynes Mathew George03c40102016-01-29 17:57:48 -0800382 if (adev->adm_request_focus_v2) {
383 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
384 } else if (adev->adm_request_focus) {
385 adev->adm_request_focus(adev->adm_data, out->handle);
386 }
387}
388
389static void request_in_focus(struct stream_in *in, long ns)
390{
391 struct audio_device *adev = in->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, in->capture_handle, ns);
395 } else if (adev->adm_request_focus) {
396 adev->adm_request_focus(adev->adm_data, in->capture_handle);
397 }
398}
399
400static void release_out_focus(struct stream_out *out, long ns __unused)
401{
402 struct audio_device *adev = out->dev;
403
404 if (adev->adm_abandon_focus)
405 adev->adm_abandon_focus(adev->adm_data, out->handle);
406}
407
408static void release_in_focus(struct stream_in *in, long ns __unused)
409{
410 struct audio_device *adev = in->dev;
411 if (adev->adm_abandon_focus)
412 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
413}
414
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700415static int parse_snd_card_status(struct str_parms * parms, int * card,
416 card_status_t * status)
417{
418 char value[32]={0};
419 char state[32]={0};
420
421 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
422
423 if (ret < 0)
424 return -1;
425
426 // sscanf should be okay as value is of max length 32.
427 // same as sizeof state.
428 if (sscanf(value, "%d,%s", card, state) < 2)
429 return -1;
430
431 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
432 CARD_STATUS_OFFLINE;
433 return 0;
434}
435
vivek mehta1a9b7c02015-06-25 11:49:38 -0700436__attribute__ ((visibility ("default")))
437bool audio_hw_send_gain_dep_calibration(int level) {
438 bool ret_val = false;
439 ALOGV("%s: enter ... ", __func__);
440
441 pthread_mutex_lock(&adev_init_lock);
442
443 if (adev != NULL && adev->platform != NULL) {
444 pthread_mutex_lock(&adev->lock);
445 ret_val = platform_send_gain_dep_cal(adev->platform, level);
446 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700447
448 // if cal set fails, cache level info
449 // if cal set succeds, reset known last cal set
450 if (!ret_val)
451 last_known_cal_step = level;
452 else if (last_known_cal_step != -1)
453 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700454 } else {
455 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
456 }
457
458 pthread_mutex_unlock(&adev_init_lock);
459
460 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
461 return ret_val;
462}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700463
vivek mehtaa8d7c922016-05-25 14:40:44 -0700464__attribute__ ((visibility ("default")))
465int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
466 int table_size) {
467 int ret_val = 0;
468 ALOGV("%s: enter ... ", __func__);
469
470 pthread_mutex_lock(&adev_init_lock);
471 if (adev == NULL) {
472 ALOGW("%s: adev is NULL .... ", __func__);
473 goto done;
474 }
475
476 pthread_mutex_lock(&adev->lock);
477 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
478 pthread_mutex_unlock(&adev->lock);
479done:
480 pthread_mutex_unlock(&adev_init_lock);
481 ALOGV("%s: exit ... ", __func__);
482 return ret_val;
483}
484
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700485static bool is_supported_format(audio_format_t format)
486{
Eric Laurent8251ac82014-07-23 11:00:25 -0700487 switch (format) {
488 case AUDIO_FORMAT_MP3:
489 case AUDIO_FORMAT_AAC_LC:
490 case AUDIO_FORMAT_AAC_HE_V1:
491 case AUDIO_FORMAT_AAC_HE_V2:
492 return true;
493 default:
494 break;
495 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700496 return false;
497}
498
Haynes Mathew George03c40102016-01-29 17:57:48 -0800499static inline bool is_mmap_usecase(audio_usecase_t uc_id)
500{
501 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
502 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
503}
504
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700505static int get_snd_codec_id(audio_format_t format)
506{
507 int id = 0;
508
Eric Laurent8251ac82014-07-23 11:00:25 -0700509 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700510 case AUDIO_FORMAT_MP3:
511 id = SND_AUDIOCODEC_MP3;
512 break;
513 case AUDIO_FORMAT_AAC:
514 id = SND_AUDIOCODEC_AAC;
515 break;
516 default:
517 ALOGE("%s: Unsupported audio format", __func__);
518 }
519
520 return id;
521}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800522
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800523static int audio_ssr_status(struct audio_device *adev)
524{
525 int ret = 0;
526 struct mixer_ctl *ctl;
527 const char *mixer_ctl_name = "Audio SSR Status";
528
529 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
530 ret = mixer_ctl_get_value(ctl, 0);
531 ALOGD("%s: value: %d", __func__, ret);
532 return ret;
533}
534
vivek mehta4a824772017-06-08 19:05:49 -0700535static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
536{
537 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
538}
539
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800540int enable_audio_route(struct audio_device *adev,
541 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800542{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700543 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800544 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800545
546 if (usecase == NULL)
547 return -EINVAL;
548
549 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
550
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800551 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700552 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800553 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700554 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800555
Yamit Mehtae3b99562016-09-16 22:44:00 +0530556 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800557 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800558 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500559 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700560 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700561 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800563 ALOGV("%s: exit", __func__);
564 return 0;
565}
566
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800567int disable_audio_route(struct audio_device *adev,
568 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800569{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700570 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800571 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800572
573 if (usecase == NULL)
574 return -EINVAL;
575
576 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700577 if (usecase->type == PCM_CAPTURE)
578 snd_device = usecase->in_snd_device;
579 else
580 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800581 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500582 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700583 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700584 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800586 ALOGV("%s: exit", __func__);
587 return 0;
588}
589
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800590int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700591 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800592{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700593 int i, num_devices = 0;
594 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800595 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800596 if (snd_device < SND_DEVICE_MIN ||
597 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800598 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800599 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800600 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700601
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700602 platform_send_audio_calibration(adev->platform, snd_device);
603
vivek mehtade4849c2016-03-03 17:23:38 -0800604 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700605 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700606 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800607 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700608 }
609
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700610 /* due to the possibility of calibration overwrite between listen
611 and audio, notify sound trigger hal before audio calibration is sent */
612 audio_extn_sound_trigger_update_device_status(snd_device,
613 ST_EVENT_SND_DEVICE_BUSY);
614
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700615 if (audio_extn_spkr_prot_is_enabled())
616 audio_extn_spkr_prot_calib_cancel(adev);
617
zhaoyang yin4211fad2015-06-04 21:13:25 +0800618 audio_extn_dsm_feedback_enable(adev, snd_device, true);
619
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700620 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
621 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
622 audio_extn_spkr_prot_is_enabled()) {
623 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800624 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700625 }
626 if (audio_extn_spkr_prot_start_processing(snd_device)) {
627 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800628 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700629 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700630 } else if (platform_can_split_snd_device(snd_device,
631 &num_devices,
632 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700633 for (i = 0; i < num_devices; i++) {
634 enable_snd_device(adev, new_snd_devices[i]);
635 }
vivek mehtab6506412015-08-07 16:55:17 -0700636 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700637 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800638 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
639 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
640 ALOGE(" %s: Invalid sound device returned", __func__);
641 goto on_error;
642 }
Ed Tam70b5c142016-03-21 19:14:29 -0700643
Eric Laurent2e140aa2016-06-30 17:14:46 -0700644 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800645 audio_route_apply_and_update_path(adev->audio_route, device_name);
646 }
647on_success:
648 adev->snd_dev_ref_cnt[snd_device]++;
649 ret_val = 0;
650on_error:
651 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800652}
653
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800654int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700655 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800656{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700657 int i, num_devices = 0;
658 snd_device_t new_snd_devices[2];
659
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800660 if (snd_device < SND_DEVICE_MIN ||
661 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800662 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800663 return -EINVAL;
664 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
666 ALOGE("%s: device ref cnt is already 0", __func__);
667 return -EINVAL;
668 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800669 audio_extn_tfa_98xx_disable_speaker(snd_device);
670
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700671 adev->snd_dev_ref_cnt[snd_device]--;
672 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800673 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700674 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
675 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
676 audio_extn_spkr_prot_is_enabled()) {
677 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700678 } else if (platform_can_split_snd_device(snd_device,
679 &num_devices,
680 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700681 for (i = 0; i < num_devices; i++) {
682 disable_snd_device(adev, new_snd_devices[i]);
683 }
vivek mehtab6506412015-08-07 16:55:17 -0700684 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700685 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800686 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
687 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
688 ALOGE(" %s: Invalid sound device returned", __func__);
689 return -EINVAL;
690 }
691
Eric Laurent2e140aa2016-06-30 17:14:46 -0700692 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800693 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700694 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700695 audio_extn_sound_trigger_update_device_status(snd_device,
696 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700697 }
vivek mehtab6506412015-08-07 16:55:17 -0700698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800699 return 0;
700}
701
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700702/*
703 legend:
704 uc - existing usecase
705 new_uc - new usecase
706 d1, d11, d2 - SND_DEVICE enums
707 a1, a2 - corresponding ANDROID device enums
708 B, B1, B2 - backend strings
709
710case 1
711 uc->dev d1 (a1) B1
712 new_uc->dev d1 (a1), d2 (a2) B1, B2
713
714 resolution: disable and enable uc->dev on d1
715
716case 2
717 uc->dev d1 (a1) B1
718 new_uc->dev d11 (a1) B1
719
720 resolution: need to switch uc since d1 and d11 are related
721 (e.g. speaker and voice-speaker)
722 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
723
724case 3
725 uc->dev d1 (a1) B1
726 new_uc->dev d2 (a2) B2
727
728 resolution: no need to switch uc
729
730case 4
731 uc->dev d1 (a1) B
732 new_uc->dev d2 (a2) B
733
734 resolution: disable enable uc-dev on d2 since backends match
735 we cannot enable two streams on two different devices if they
736 share the same backend. e.g. if offload is on speaker device using
737 QUAD_MI2S backend and a low-latency stream is started on voice-handset
738 using the same backend, offload must also be switched to voice-handset.
739
740case 5
741 uc->dev d1 (a1) B
742 new_uc->dev d1 (a1), d2 (a2) B
743
744 resolution: disable enable uc-dev on d2 since backends match
745 we cannot enable two streams on two different devices if they
746 share the same backend.
747
748case 6
749 uc->dev d1 a1 B1
750 new_uc->dev d2 a1 B2
751
752 resolution: no need to switch
753
754case 7
755
756 uc->dev d1 (a1), d2 (a2) B1, B2
757 new_uc->dev d1 B1
758
759 resolution: no need to switch
760
761*/
762static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
763 struct audio_usecase *new_uc,
764 snd_device_t new_snd_device)
765{
766 audio_devices_t a1 = uc->stream.out->devices;
767 audio_devices_t a2 = new_uc->stream.out->devices;
768
769 snd_device_t d1 = uc->out_snd_device;
770 snd_device_t d2 = new_snd_device;
771
772 // Treat as a special case when a1 and a2 are not disjoint
773 if ((a1 != a2) && (a1 & a2)) {
774 snd_device_t d3[2];
775 int num_devices = 0;
776 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
777 &num_devices,
778 d3);
779 if (ret < 0) {
780 if (ret != -ENOSYS) {
781 ALOGW("%s failed to split snd_device %d",
782 __func__,
783 popcount(a1) > 1 ? d1 : d2);
784 }
785 goto end;
786 }
787
788 // NB: case 7 is hypothetical and isn't a practical usecase yet.
789 // But if it does happen, we need to give priority to d2 if
790 // the combo devices active on the existing usecase share a backend.
791 // This is because we cannot have a usecase active on a combo device
792 // and a new usecase requests one device in this combo pair.
793 if (platform_check_backends_match(d3[0], d3[1])) {
794 return d2; // case 5
795 } else {
796 return d1; // case 1
797 }
798 } else {
799 if (platform_check_backends_match(d1, d2)) {
800 return d2; // case 2, 4
801 } else {
802 return d1; // case 6, 3
803 }
804 }
805
806end:
807 return d2; // return whatever was calculated before.
808}
809
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700810static void check_and_route_playback_usecases(struct audio_device *adev,
811 struct audio_usecase *uc_info,
812 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700813{
814 struct listnode *node;
815 struct audio_usecase *usecase;
816 bool switch_device[AUDIO_USECASE_MAX];
817 int i, num_uc_to_switch = 0;
818
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700819 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
820 uc_info,
821 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700822
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700823 /*
824 * This function is to make sure that all the usecases that are active on
825 * the hardware codec backend are always routed to any one device that is
826 * handled by the hardware codec.
827 * For example, if low-latency and deep-buffer usecases are currently active
828 * on speaker and out_set_parameters(headset) is received on low-latency
829 * output, then we have to make sure deep-buffer is also switched to headset,
830 * because of the limitation that both the devices cannot be enabled
831 * at the same time as they share the same backend.
832 */
833 /* Disable all the usecases on the shared backend other than the
834 specified usecase */
835 for (i = 0; i < AUDIO_USECASE_MAX; i++)
836 switch_device[i] = false;
837
838 list_for_each(node, &adev->usecase_list) {
839 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700840 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
841 continue;
842
843 if (force_routing ||
844 (usecase->out_snd_device != snd_device &&
845 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
846 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700847 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
848 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700849 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700850 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700851 switch_device[usecase->id] = true;
852 num_uc_to_switch++;
853 }
854 }
855
856 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 list_for_each(node, &adev->usecase_list) {
858 usecase = node_to_item(node, struct audio_usecase, list);
859 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700860 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900861 }
862 }
863
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700864 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900865 list_for_each(node, &adev->usecase_list) {
866 usecase = node_to_item(node, struct audio_usecase, list);
867 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700868 d_device = derive_playback_snd_device(usecase, uc_info,
869 snd_device);
870 enable_snd_device(adev, d_device);
871 /* Update the out_snd_device before enabling the audio route */
872 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 }
874 }
875
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700876 /* Re-route all the usecases on the shared backend other than the
877 specified usecase to new snd devices */
878 list_for_each(node, &adev->usecase_list) {
879 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700880 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700881 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700882 }
883 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 }
885}
886
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700887static void check_and_route_capture_usecases(struct audio_device *adev,
888 struct audio_usecase *uc_info,
889 snd_device_t snd_device)
890{
891 struct listnode *node;
892 struct audio_usecase *usecase;
893 bool switch_device[AUDIO_USECASE_MAX];
894 int i, num_uc_to_switch = 0;
895
vivek mehta4ed66e62016-04-15 23:33:34 -0700896 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
897
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700898 /*
899 * This function is to make sure that all the active capture usecases
900 * are always routed to the same input sound device.
901 * For example, if audio-record and voice-call usecases are currently
902 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
903 * is received for voice call then we have to make sure that audio-record
904 * usecase is also switched to earpiece i.e. voice-dmic-ef,
905 * because of the limitation that two devices cannot be enabled
906 * at the same time if they share the same backend.
907 */
908 for (i = 0; i < AUDIO_USECASE_MAX; i++)
909 switch_device[i] = false;
910
911 list_for_each(node, &adev->usecase_list) {
912 usecase = node_to_item(node, struct audio_usecase, list);
913 if (usecase->type != PCM_PLAYBACK &&
914 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700915 usecase->in_snd_device != snd_device &&
916 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700917 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
918 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700919 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700920 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700921 switch_device[usecase->id] = true;
922 num_uc_to_switch++;
923 }
924 }
925
926 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700927 list_for_each(node, &adev->usecase_list) {
928 usecase = node_to_item(node, struct audio_usecase, list);
929 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700930 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700931 }
932 }
933
934 list_for_each(node, &adev->usecase_list) {
935 usecase = node_to_item(node, struct audio_usecase, list);
936 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700937 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700938 }
939 }
940
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700941 /* Re-route all the usecases on the shared backend other than the
942 specified usecase to new snd devices */
943 list_for_each(node, &adev->usecase_list) {
944 usecase = node_to_item(node, struct audio_usecase, list);
945 /* Update the in_snd_device only before enabling the audio route */
946 if (switch_device[usecase->id] ) {
947 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700948 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 }
950 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700951 }
952}
953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800954/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700955static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800956{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700957 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700958 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800959
960 switch (channels) {
961 /*
962 * Do not handle stereo output in Multi-channel cases
963 * Stereo case is handled in normal playback path
964 */
965 case 6:
966 ALOGV("%s: HDMI supports 5.1", __func__);
967 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
968 break;
969 case 8:
970 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
971 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
972 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
973 break;
974 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700975 ALOGE("HDMI does not support multi channel playback");
976 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977 break;
978 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700979 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980}
981
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700982static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
983 uint32_t *supported_sample_rates __unused,
984 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800985{
Haynes Mathew George569b7482017-05-08 14:44:27 -0700986 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
987 supported_sample_rates,
988 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800989#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -0700990 for (ssize_t i=0; i<count; i++) {
991 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
992 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800993 }
994#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -0700995 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800996}
997
Haynes Mathew George569b7482017-05-08 14:44:27 -0700998static int read_usb_sup_channel_masks(bool is_playback,
999 audio_channel_mask_t *supported_channel_masks,
1000 uint32_t max_masks __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001001{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001002 int channels = audio_extn_usb_get_max_channels(is_playback);
1003 if (is_playback) {
1004 supported_channel_masks[0] =
1005 channels < 3 ? audio_channel_out_mask_from_count(channels) :
1006 audio_channel_mask_for_index_assignment_from_count(channels);
1007 } else {
1008 supported_channel_masks[0] = audio_channel_in_mask_from_count(channels);
1009 }
1010 ALOGV("%s: %s supported ch %d", __func__,
1011 is_playback ? "P" : "C", channels);
1012 return 1;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001013}
1014
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001015static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001016 audio_format_t *supported_formats,
1017 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001018{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001019 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001020 switch (bitwidth) {
1021 case 24:
1022 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001023 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001024 break;
1025 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001026 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001027 break;
1028 case 16:
1029 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001030 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001031 break;
1032 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001033 ALOGV("%s: %s supported format %d", __func__,
1034 is_playback ? "P" : "C", bitwidth);
1035 return 1;
1036}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001037
Haynes Mathew George569b7482017-05-08 14:44:27 -07001038static int read_usb_sup_params_and_compare(bool is_playback,
1039 audio_format_t *format,
1040 audio_format_t *supported_formats,
1041 uint32_t max_formats,
1042 audio_channel_mask_t *mask,
1043 audio_channel_mask_t *supported_channel_masks,
1044 uint32_t max_masks,
1045 uint32_t *rate,
1046 uint32_t *supported_sample_rates,
1047 uint32_t max_rates) {
1048 int ret = 0;
1049 int num_formats;
1050 int num_masks;
1051 int num_rates;
1052 int i;
1053
1054 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1055 max_formats);
1056 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1057 max_masks);
1058 num_rates = read_usb_sup_sample_rates(is_playback,
1059 supported_sample_rates, max_rates);
1060
1061#define LUT(table, len, what, dflt) \
1062 for (i=0; i<len && (table[i] != what); i++); \
1063 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1064
1065 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1066 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1067 LUT(supported_sample_rates, num_rates, *rate, 0);
1068
1069#undef LUT
1070 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001071}
1072
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001073static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1074{
1075 struct audio_usecase *usecase;
1076 struct listnode *node;
1077
1078 list_for_each(node, &adev->usecase_list) {
1079 usecase = node_to_item(node, struct audio_usecase, list);
1080 if (usecase->type == VOICE_CALL) {
1081 ALOGV("%s: usecase id %d", __func__, usecase->id);
1082 return usecase->id;
1083 }
1084 }
1085 return USECASE_INVALID;
1086}
1087
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001088struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1089 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001090{
1091 struct audio_usecase *usecase;
1092 struct listnode *node;
1093
1094 list_for_each(node, &adev->usecase_list) {
1095 usecase = node_to_item(node, struct audio_usecase, list);
1096 if (usecase->id == uc_id)
1097 return usecase;
1098 }
1099 return NULL;
1100}
1101
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001102int select_devices(struct audio_device *adev,
1103 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001105 snd_device_t out_snd_device = SND_DEVICE_NONE;
1106 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 struct audio_usecase *usecase = NULL;
1108 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001109 struct audio_usecase *hfp_usecase = NULL;
1110 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001111 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001113
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114 usecase = get_usecase_from_list(adev, uc_id);
1115 if (usecase == NULL) {
1116 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1117 return -EINVAL;
1118 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001119
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001120 if ((usecase->type == VOICE_CALL) ||
1121 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001122 out_snd_device = platform_get_output_snd_device(adev->platform,
1123 usecase->stream.out->devices);
1124 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001125 usecase->devices = usecase->stream.out->devices;
1126 } else {
1127 /*
1128 * If the voice call is active, use the sound devices of voice call usecase
1129 * so that it would not result any device switch. All the usecases will
1130 * be switched to new device when select_devices() is called for voice call
1131 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001132 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001134 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001135 vc_usecase = get_usecase_from_list(adev,
1136 get_voice_usecase_id_from_list(adev));
1137 if ((vc_usecase != NULL) &&
1138 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1139 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001140 in_snd_device = vc_usecase->in_snd_device;
1141 out_snd_device = vc_usecase->out_snd_device;
1142 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001143 } else if (audio_extn_hfp_is_active(adev)) {
1144 hfp_ucid = audio_extn_hfp_get_usecase();
1145 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1146 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1147 in_snd_device = hfp_usecase->in_snd_device;
1148 out_snd_device = hfp_usecase->out_snd_device;
1149 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001150 }
1151 if (usecase->type == PCM_PLAYBACK) {
1152 usecase->devices = usecase->stream.out->devices;
1153 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001154 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001155 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001156 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001157 if (usecase->stream.out == adev->primary_output &&
1158 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001159 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1160 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001161 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001162 select_devices(adev, adev->active_input->usecase);
1163 }
1164 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001165 } else if (usecase->type == PCM_CAPTURE) {
1166 usecase->devices = usecase->stream.in->device;
1167 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001168 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001169 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001170 if (adev->active_input &&
1171 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1172 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001173 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001174 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1175 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1176 } else if (adev->primary_output) {
1177 out_device = adev->primary_output->devices;
1178 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001179 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001180 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001181 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001182 }
1183 }
1184
1185 if (out_snd_device == usecase->out_snd_device &&
1186 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001187 return 0;
1188 }
1189
Eric Laurent2bafff12016-03-17 12:17:23 -07001190 if (out_snd_device != SND_DEVICE_NONE &&
1191 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1192 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1193 __func__,
1194 use_case_table[uc_id],
1195 adev->last_logged_snd_device[uc_id][0],
1196 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1197 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1198 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1199 -1,
1200 out_snd_device,
1201 platform_get_snd_device_name(out_snd_device),
1202 platform_get_snd_device_acdb_id(out_snd_device));
1203 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1204 }
1205 if (in_snd_device != SND_DEVICE_NONE &&
1206 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1207 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1208 __func__,
1209 use_case_table[uc_id],
1210 adev->last_logged_snd_device[uc_id][1],
1211 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1212 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1213 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1214 -1,
1215 in_snd_device,
1216 platform_get_snd_device_name(in_snd_device),
1217 platform_get_snd_device_acdb_id(in_snd_device));
1218 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1219 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001221 /*
1222 * Limitation: While in call, to do a device switch we need to disable
1223 * and enable both RX and TX devices though one of them is same as current
1224 * device.
1225 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001226 if ((usecase->type == VOICE_CALL) &&
1227 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1228 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001229 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001230 /* Disable sidetone only if voice call already exists */
1231 if (voice_is_call_state_active(adev))
1232 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001233 }
1234
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001235 /* Disable current sound devices */
1236 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001237 disable_audio_route(adev, usecase);
1238 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001239 }
1240
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001241 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001242 disable_audio_route(adev, usecase);
1243 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001244 }
1245
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001246 /* Applicable only on the targets that has external modem.
1247 * New device information should be sent to modem before enabling
1248 * the devices to reduce in-call device switch time.
1249 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001250 if ((usecase->type == VOICE_CALL) &&
1251 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1252 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001253 status = platform_switch_voice_call_enable_device_config(adev->platform,
1254 out_snd_device,
1255 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001256 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001257
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001258 /* Enable new sound devices */
1259 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001260 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001261 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001262 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001263 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 }
1265
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001266 if (in_snd_device != SND_DEVICE_NONE) {
1267 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001268 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001269 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001270
Eric Laurentb23d5282013-05-14 15:27:20 -07001271 if (usecase->type == VOICE_CALL)
1272 status = platform_switch_voice_call_device_post(adev->platform,
1273 out_snd_device,
1274 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001275
sangwoo170731f2013-06-08 15:36:36 +09001276 usecase->in_snd_device = in_snd_device;
1277 usecase->out_snd_device = out_snd_device;
1278
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001279 audio_extn_tfa_98xx_set_mode();
1280
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001281 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001282
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001283 /* Applicable only on the targets that has external modem.
1284 * Enable device command should be sent to modem only after
1285 * enabling voice call mixer controls
1286 */
vivek mehta765eb642015-08-07 19:46:06 -07001287 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001288 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1289 out_snd_device,
1290 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001291 /* Enable sidetone only if voice call already exists */
1292 if (voice_is_call_state_active(adev))
1293 voice_set_sidetone(adev, out_snd_device, true);
1294 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001295
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001296 return status;
1297}
1298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001299static int stop_input_stream(struct stream_in *in)
1300{
1301 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302 struct audio_usecase *uc_info;
1303 struct audio_device *adev = in->dev;
1304
Eric Laurentc8400632013-02-14 19:04:54 -08001305 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001306
Eric Laurent994a6932013-07-17 11:51:42 -07001307 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001308 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001309 uc_info = get_usecase_from_list(adev, in->usecase);
1310 if (uc_info == NULL) {
1311 ALOGE("%s: Could not find the usecase (%d) in the list",
1312 __func__, in->usecase);
1313 return -EINVAL;
1314 }
1315
vivek mehta781065c2017-04-04 12:55:01 -07001316 /* Close in-call recording streams */
1317 voice_check_and_stop_incall_rec_usecase(adev, in);
1318
Eric Laurent150dbfe2013-02-27 14:31:02 -08001319 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001320 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001321
1322 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001323 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001324
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001325 list_remove(&uc_info->list);
1326 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001327
Eric Laurent994a6932013-07-17 11:51:42 -07001328 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001329 return ret;
1330}
1331
1332int start_input_stream(struct stream_in *in)
1333{
1334 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001335 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001336 struct audio_usecase *uc_info;
1337 struct audio_device *adev = in->dev;
1338
Eric Laurent994a6932013-07-17 11:51:42 -07001339 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001340
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001341 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1342 return -EIO;
1343
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001344 if (in->card_status == CARD_STATUS_OFFLINE ||
1345 adev->card_status == CARD_STATUS_OFFLINE) {
1346 ALOGW("in->card_status or adev->card_status offline, try again");
1347 ret = -EAGAIN;
1348 goto error_config;
1349 }
1350
vivek mehta781065c2017-04-04 12:55:01 -07001351 /* Check if source matches incall recording usecase criteria */
1352 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1353 if (ret)
1354 goto error_config;
1355 else
1356 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1357
Eric Laurentb23d5282013-05-14 15:27:20 -07001358 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001359 if (in->pcm_device_id < 0) {
1360 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1361 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001362 ret = -EINVAL;
1363 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001364 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001365
1366 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1368 uc_info->id = in->usecase;
1369 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001370 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001371 uc_info->devices = in->device;
1372 uc_info->in_snd_device = SND_DEVICE_NONE;
1373 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001375 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001376
1377 audio_extn_perf_lock_acquire();
1378
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001379 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001380
Eric Laurent0e46adf2016-12-16 12:49:24 -08001381 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001382 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001383 ALOGE("%s: pcm stream not ready", __func__);
1384 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001385 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001386 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001387 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001388 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1389 goto error_open;
1390 }
1391 } else {
1392 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1393 unsigned int pcm_open_retry_count = 0;
1394
1395 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1396 flags |= PCM_MMAP | PCM_NOIRQ;
1397 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1398 } else if (in->realtime) {
1399 flags |= PCM_MMAP | PCM_NOIRQ;
1400 }
1401
1402 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1403 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1404
1405 while (1) {
1406 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1407 flags, &in->config);
1408 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1409 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1410 if (in->pcm != NULL) {
1411 pcm_close(in->pcm);
1412 in->pcm = NULL;
1413 }
1414 if (pcm_open_retry_count-- == 0) {
1415 ret = -EIO;
1416 goto error_open;
1417 }
1418 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1419 continue;
1420 }
1421 break;
1422 }
1423
1424 ALOGV("%s: pcm_prepare", __func__);
1425 ret = pcm_prepare(in->pcm);
1426 if (ret < 0) {
1427 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001428 pcm_close(in->pcm);
1429 in->pcm = NULL;
1430 goto error_open;
1431 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001432 if (in->realtime) {
1433 ret = pcm_start(in->pcm);
1434 if (ret < 0) {
1435 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1436 pcm_close(in->pcm);
1437 in->pcm = NULL;
1438 goto error_open;
1439 }
1440 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001441 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001442 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001443 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001444 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001445
Eric Laurent0e46adf2016-12-16 12:49:24 -08001446 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001447
1448error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001449 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001450 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001451
1452error_config:
1453 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001454 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001455 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001456}
1457
Eric Laurenta1478072015-09-21 17:21:52 -07001458void lock_input_stream(struct stream_in *in)
1459{
1460 pthread_mutex_lock(&in->pre_lock);
1461 pthread_mutex_lock(&in->lock);
1462 pthread_mutex_unlock(&in->pre_lock);
1463}
1464
1465void lock_output_stream(struct stream_out *out)
1466{
1467 pthread_mutex_lock(&out->pre_lock);
1468 pthread_mutex_lock(&out->lock);
1469 pthread_mutex_unlock(&out->pre_lock);
1470}
1471
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001472/* must be called with out->lock locked */
1473static int send_offload_cmd_l(struct stream_out* out, int command)
1474{
1475 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1476
1477 ALOGVV("%s %d", __func__, command);
1478
1479 cmd->cmd = command;
1480 list_add_tail(&out->offload_cmd_list, &cmd->node);
1481 pthread_cond_signal(&out->offload_cond);
1482 return 0;
1483}
1484
1485/* must be called iwth out->lock locked */
1486static void stop_compressed_output_l(struct stream_out *out)
1487{
1488 out->offload_state = OFFLOAD_STATE_IDLE;
1489 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001490 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001491 if (out->compr != NULL) {
1492 compress_stop(out->compr);
1493 while (out->offload_thread_blocked) {
1494 pthread_cond_wait(&out->cond, &out->lock);
1495 }
1496 }
1497}
1498
1499static void *offload_thread_loop(void *context)
1500{
1501 struct stream_out *out = (struct stream_out *) context;
1502 struct listnode *item;
1503
1504 out->offload_state = OFFLOAD_STATE_IDLE;
1505 out->playback_started = 0;
1506
1507 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1508 set_sched_policy(0, SP_FOREGROUND);
1509 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1510
1511 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001512 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001513 for (;;) {
1514 struct offload_cmd *cmd = NULL;
1515 stream_callback_event_t event;
1516 bool send_callback = false;
1517
1518 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1519 __func__, list_empty(&out->offload_cmd_list),
1520 out->offload_state);
1521 if (list_empty(&out->offload_cmd_list)) {
1522 ALOGV("%s SLEEPING", __func__);
1523 pthread_cond_wait(&out->offload_cond, &out->lock);
1524 ALOGV("%s RUNNING", __func__);
1525 continue;
1526 }
1527
1528 item = list_head(&out->offload_cmd_list);
1529 cmd = node_to_item(item, struct offload_cmd, node);
1530 list_remove(item);
1531
1532 ALOGVV("%s STATE %d CMD %d out->compr %p",
1533 __func__, out->offload_state, cmd->cmd, out->compr);
1534
1535 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1536 free(cmd);
1537 break;
1538 }
1539
1540 if (out->compr == NULL) {
1541 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001542 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001543 pthread_cond_signal(&out->cond);
1544 continue;
1545 }
1546 out->offload_thread_blocked = true;
1547 pthread_mutex_unlock(&out->lock);
1548 send_callback = false;
1549 switch(cmd->cmd) {
1550 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1551 compress_wait(out->compr, -1);
1552 send_callback = true;
1553 event = STREAM_CBK_EVENT_WRITE_READY;
1554 break;
1555 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001556 compress_next_track(out->compr);
1557 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001558 send_callback = true;
1559 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001560 /* Resend the metadata for next iteration */
1561 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001562 break;
1563 case OFFLOAD_CMD_DRAIN:
1564 compress_drain(out->compr);
1565 send_callback = true;
1566 event = STREAM_CBK_EVENT_DRAIN_READY;
1567 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001568 case OFFLOAD_CMD_ERROR:
1569 send_callback = true;
1570 event = STREAM_CBK_EVENT_ERROR;
1571 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001572 default:
1573 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1574 break;
1575 }
Eric Laurenta1478072015-09-21 17:21:52 -07001576 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001577 out->offload_thread_blocked = false;
1578 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001579 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001580 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001581 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001582 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001583 free(cmd);
1584 }
1585
1586 pthread_cond_signal(&out->cond);
1587 while (!list_empty(&out->offload_cmd_list)) {
1588 item = list_head(&out->offload_cmd_list);
1589 list_remove(item);
1590 free(node_to_item(item, struct offload_cmd, node));
1591 }
1592 pthread_mutex_unlock(&out->lock);
1593
1594 return NULL;
1595}
1596
1597static int create_offload_callback_thread(struct stream_out *out)
1598{
1599 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1600 list_init(&out->offload_cmd_list);
1601 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1602 offload_thread_loop, out);
1603 return 0;
1604}
1605
1606static int destroy_offload_callback_thread(struct stream_out *out)
1607{
Eric Laurenta1478072015-09-21 17:21:52 -07001608 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001609 stop_compressed_output_l(out);
1610 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1611
1612 pthread_mutex_unlock(&out->lock);
1613 pthread_join(out->offload_thread, (void **) NULL);
1614 pthread_cond_destroy(&out->offload_cond);
1615
1616 return 0;
1617}
1618
Eric Laurent07eeafd2013-10-06 12:52:49 -07001619static bool allow_hdmi_channel_config(struct audio_device *adev)
1620{
1621 struct listnode *node;
1622 struct audio_usecase *usecase;
1623 bool ret = true;
1624
1625 list_for_each(node, &adev->usecase_list) {
1626 usecase = node_to_item(node, struct audio_usecase, list);
1627 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1628 /*
1629 * If voice call is already existing, do not proceed further to avoid
1630 * disabling/enabling both RX and TX devices, CSD calls, etc.
1631 * Once the voice call done, the HDMI channels can be configured to
1632 * max channels of remaining use cases.
1633 */
1634 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001635 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001636 __func__);
1637 ret = false;
1638 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001639 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1640 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001641 "no change in HDMI channels", __func__);
1642 ret = false;
1643 break;
1644 }
1645 }
1646 }
1647 return ret;
1648}
1649
1650static int check_and_set_hdmi_channels(struct audio_device *adev,
1651 unsigned int channels)
1652{
1653 struct listnode *node;
1654 struct audio_usecase *usecase;
1655
1656 /* Check if change in HDMI channel config is allowed */
1657 if (!allow_hdmi_channel_config(adev))
1658 return 0;
1659
1660 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001661 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001662 return 0;
1663 }
1664
1665 platform_set_hdmi_channels(adev->platform, channels);
1666 adev->cur_hdmi_channels = channels;
1667
1668 /*
1669 * Deroute all the playback streams routed to HDMI so that
1670 * the back end is deactivated. Note that backend will not
1671 * be deactivated if any one stream is connected to it.
1672 */
1673 list_for_each(node, &adev->usecase_list) {
1674 usecase = node_to_item(node, struct audio_usecase, list);
1675 if (usecase->type == PCM_PLAYBACK &&
1676 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001677 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001678 }
1679 }
1680
1681 /*
1682 * Enable all the streams disabled above. Now the HDMI backend
1683 * will be activated with new channel configuration
1684 */
1685 list_for_each(node, &adev->usecase_list) {
1686 usecase = node_to_item(node, struct audio_usecase, list);
1687 if (usecase->type == PCM_PLAYBACK &&
1688 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001689 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001690 }
1691 }
1692
1693 return 0;
1694}
1695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696static int stop_output_stream(struct stream_out *out)
1697{
1698 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699 struct audio_usecase *uc_info;
1700 struct audio_device *adev = out->dev;
1701
Eric Laurent994a6932013-07-17 11:51:42 -07001702 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001703 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704 uc_info = get_usecase_from_list(adev, out->usecase);
1705 if (uc_info == NULL) {
1706 ALOGE("%s: Could not find the usecase (%d) in the list",
1707 __func__, out->usecase);
1708 return -EINVAL;
1709 }
1710
Haynes Mathew George41f86652014-06-17 14:22:15 -07001711 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1712 if (adev->visualizer_stop_output != NULL)
1713 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1714 if (adev->offload_effects_stop_output != NULL)
1715 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1716 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001717
Eric Laurent150dbfe2013-02-27 14:31:02 -08001718 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001719 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001720
1721 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001722 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001724 list_remove(&uc_info->list);
1725 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726
Eric Laurent0499d4f2014-08-25 22:39:29 -05001727 audio_extn_extspk_update(adev->extspk);
1728
Eric Laurent07eeafd2013-10-06 12:52:49 -07001729 /* Must be called after removing the usecase from list */
1730 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1731 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1732
Eric Laurent994a6932013-07-17 11:51:42 -07001733 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734 return ret;
1735}
1736
1737int start_output_stream(struct stream_out *out)
1738{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740 struct audio_usecase *uc_info;
1741 struct audio_device *adev = out->dev;
1742
Eric Laurent994a6932013-07-17 11:51:42 -07001743 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001744 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001745
1746 if (out->card_status == CARD_STATUS_OFFLINE ||
1747 adev->card_status == CARD_STATUS_OFFLINE) {
1748 ALOGW("out->card_status or adev->card_status offline, try again");
1749 ret = -EAGAIN;
1750 goto error_config;
1751 }
1752
Eric Laurentb23d5282013-05-14 15:27:20 -07001753 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 if (out->pcm_device_id < 0) {
1755 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1756 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001757 ret = -EINVAL;
1758 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759 }
1760
1761 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1762 uc_info->id = out->usecase;
1763 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001764 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001765 uc_info->devices = out->devices;
1766 uc_info->in_snd_device = SND_DEVICE_NONE;
1767 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768
Eric Laurent07eeafd2013-10-06 12:52:49 -07001769 /* This must be called before adding this usecase to the list */
1770 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1771 check_and_set_hdmi_channels(adev, out->config.channels);
1772
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001773 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001775 audio_extn_perf_lock_acquire();
1776
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001777 select_devices(adev, out->usecase);
1778
Eric Laurent0499d4f2014-08-25 22:39:29 -05001779 audio_extn_extspk_update(adev->extspk);
1780
Andy Hung31aca912014-03-20 17:14:59 -07001781 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001782 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001783 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1784 out->pcm = NULL;
1785 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1786 COMPRESS_IN, &out->compr_config);
1787 if (out->compr && !is_compress_ready(out->compr)) {
1788 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1789 compress_close(out->compr);
1790 out->compr = NULL;
1791 ret = -EIO;
1792 goto error_open;
1793 }
1794 if (out->offload_callback)
1795 compress_nonblock(out->compr, out->non_blocking);
1796
1797 if (adev->visualizer_start_output != NULL)
1798 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1799 if (adev->offload_effects_start_output != NULL)
1800 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1801 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001802 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001803 ALOGE("%s: pcm stream not ready", __func__);
1804 goto error_open;
1805 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001806 ret = pcm_start(out->pcm);
1807 if (ret < 0) {
1808 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1809 goto error_open;
1810 }
1811 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001812 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001813 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001814
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001815 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1816 flags |= PCM_MMAP | PCM_NOIRQ;
1817 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001818 } else if (out->realtime) {
1819 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001820 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001821
1822 while (1) {
1823 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1824 flags, &out->config);
1825 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1826 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1827 if (out->pcm != NULL) {
1828 pcm_close(out->pcm);
1829 out->pcm = NULL;
1830 }
1831 if (pcm_open_retry_count-- == 0) {
1832 ret = -EIO;
1833 goto error_open;
1834 }
1835 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1836 continue;
1837 }
1838 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001839 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001840 ALOGV("%s: pcm_prepare", __func__);
1841 if (pcm_is_ready(out->pcm)) {
1842 ret = pcm_prepare(out->pcm);
1843 if (ret < 0) {
1844 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1845 pcm_close(out->pcm);
1846 out->pcm = NULL;
1847 goto error_open;
1848 }
1849 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001850 if (out->realtime) {
1851 ret = pcm_start(out->pcm);
1852 if (ret < 0) {
1853 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1854 pcm_close(out->pcm);
1855 out->pcm = NULL;
1856 goto error_open;
1857 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001858 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001859 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001860 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001861 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001862 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001863 audio_extn_utils_send_app_type_gain(out->dev,
1864 out->app_type_cfg.app_type,
1865 &out->app_type_cfg.gain[0]);
Eric Laurent994a6932013-07-17 11:51:42 -07001866 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001867 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001868error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001869 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001870 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001871error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001872 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001873}
1874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001875static int check_input_parameters(uint32_t sample_rate,
1876 audio_format_t format,
1877 int channel_count)
1878{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001879 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1880 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
1881 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED)) {
vivek mehtadae44712015-07-27 14:13:18 -07001882 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1883 return -EINVAL;
1884 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885
vivek mehtadae44712015-07-27 14:13:18 -07001886 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001887 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001888 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1889 return -EINVAL;
1890 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891
1892 switch (sample_rate) {
1893 case 8000:
1894 case 11025:
1895 case 12000:
1896 case 16000:
1897 case 22050:
1898 case 24000:
1899 case 32000:
1900 case 44100:
1901 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001902 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001903 break;
1904 default:
vivek mehtadae44712015-07-27 14:13:18 -07001905 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906 return -EINVAL;
1907 }
1908
1909 return 0;
1910}
1911
vivek mehtaa68fea62017-06-08 19:04:02 -07001912static size_t get_stream_buffer_size(size_t duration_ms,
1913 uint32_t sample_rate,
1914 audio_format_t format,
1915 int channel_count,
1916 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917{
1918 size_t size = 0;
1919
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001920 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1921 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922
vivek mehtaa68fea62017-06-08 19:04:02 -07001923 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001924 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001925 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001926
1927 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928
Glenn Kasten4f993392014-05-14 07:30:48 -07001929 /* make sure the size is multiple of 32 bytes
1930 * At 48 kHz mono 16-bit PCM:
1931 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1932 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1933 */
1934 size += 0x1f;
1935 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001936
1937 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938}
1939
1940static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1941{
1942 struct stream_out *out = (struct stream_out *)stream;
1943
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001944 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945}
1946
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001947static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001948{
1949 return -ENOSYS;
1950}
1951
1952static size_t out_get_buffer_size(const struct audio_stream *stream)
1953{
1954 struct stream_out *out = (struct stream_out *)stream;
1955
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001956 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1957 return out->compr_config.fragment_size;
1958 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001959 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001960 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961}
1962
1963static uint32_t out_get_channels(const struct audio_stream *stream)
1964{
1965 struct stream_out *out = (struct stream_out *)stream;
1966
1967 return out->channel_mask;
1968}
1969
1970static audio_format_t out_get_format(const struct audio_stream *stream)
1971{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001972 struct stream_out *out = (struct stream_out *)stream;
1973
1974 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001975}
1976
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001977static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001978{
1979 return -ENOSYS;
1980}
1981
1982static int out_standby(struct audio_stream *stream)
1983{
1984 struct stream_out *out = (struct stream_out *)stream;
1985 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001986 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001987
Eric Laurent994a6932013-07-17 11:51:42 -07001988 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001989 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001990
Eric Laurenta1478072015-09-21 17:21:52 -07001991 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001992 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001993 if (adev->adm_deregister_stream)
1994 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001995 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001997 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1998 if (out->pcm) {
1999 pcm_close(out->pcm);
2000 out->pcm = NULL;
2001 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002002 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002003 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002004 out->playback_started = false;
2005 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002006 } else {
2007 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002008 out->gapless_mdata.encoder_delay = 0;
2009 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002010 if (out->compr != NULL) {
2011 compress_close(out->compr);
2012 out->compr = NULL;
2013 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002014 }
Phil Burkbc991042017-02-24 08:06:44 -08002015 if (do_stop) {
2016 stop_output_stream(out);
2017 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002018 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002019 }
2020 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002021 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022 return 0;
2023}
2024
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002025static int out_on_error(struct audio_stream *stream)
2026{
2027 struct stream_out *out = (struct stream_out *)stream;
2028 struct audio_device *adev = out->dev;
2029 bool do_standby = false;
2030
2031 lock_output_stream(out);
2032 if (!out->standby) {
2033 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2034 stop_compressed_output_l(out);
2035 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2036 } else
2037 do_standby = true;
2038 }
2039 pthread_mutex_unlock(&out->lock);
2040
2041 if (do_standby)
2042 return out_standby(&out->stream.common);
2043
2044 return 0;
2045}
2046
Andy Hung7401c7c2016-09-21 12:41:21 -07002047static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048{
Andy Hung7401c7c2016-09-21 12:41:21 -07002049 struct stream_out *out = (struct stream_out *)stream;
2050
2051 // We try to get the lock for consistency,
2052 // but it isn't necessary for these variables.
2053 // If we're not in standby, we may be blocked on a write.
2054 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2055 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2056 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2057
2058 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002059 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002060 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002061
2062 // dump error info
2063 (void)error_log_dump(
2064 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hung3ba2c922017-06-15 17:48:35 -07002065
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066 return 0;
2067}
2068
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002069static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2070{
2071 int ret = 0;
2072 char value[32];
2073 struct compr_gapless_mdata tmp_mdata;
2074
2075 if (!out || !parms) {
2076 return -EINVAL;
2077 }
2078
2079 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2080 if (ret >= 0) {
2081 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2082 } else {
2083 return -EINVAL;
2084 }
2085
2086 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2087 if (ret >= 0) {
2088 tmp_mdata.encoder_padding = atoi(value);
2089 } else {
2090 return -EINVAL;
2091 }
2092
2093 out->gapless_mdata = tmp_mdata;
2094 out->send_new_metadata = 1;
2095 ALOGV("%s new encoder delay %u and padding %u", __func__,
2096 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2097
2098 return 0;
2099}
2100
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002101static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2102{
2103 return out == adev->primary_output || out == adev->voice_tx_output;
2104}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002105
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2107{
2108 struct stream_out *out = (struct stream_out *)stream;
2109 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002110 struct audio_usecase *usecase;
2111 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112 struct str_parms *parms;
2113 char value[32];
2114 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002115 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002116 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002117
Eric Laurent2e140aa2016-06-30 17:14:46 -07002118 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002119 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 parms = str_parms_create_str(kvpairs);
2121 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2122 if (ret >= 0) {
2123 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002124 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002125 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002127 /*
2128 * When HDMI cable is unplugged the music playback is paused and
2129 * the policy manager sends routing=0. But the audioflinger
2130 * continues to write data until standby time (3sec).
2131 * As the HDMI core is turned off, the write gets blocked.
2132 * Avoid this by routing audio to speaker until standby.
2133 */
2134 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2135 val == AUDIO_DEVICE_NONE) {
2136 val = AUDIO_DEVICE_OUT_SPEAKER;
2137 }
2138
2139 /*
2140 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002141 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002142 * the select_devices(). But how do we undo this?
2143 *
2144 * For example, music playback is active on headset (deep-buffer usecase)
2145 * and if we go to ringtones and select a ringtone, low-latency usecase
2146 * will be started on headset+speaker. As we can't enable headset+speaker
2147 * and headset devices at the same time, select_devices() switches the music
2148 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2149 * So when the ringtone playback is completed, how do we undo the same?
2150 *
2151 * We are relying on the out_set_parameters() call on deep-buffer output,
2152 * once the ringtone playback is ended.
2153 * NOTE: We should not check if the current devices are same as new devices.
2154 * Because select_devices() must be called to switch back the music
2155 * playback to headset.
2156 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002157 audio_devices_t new_dev = val;
2158 if (new_dev != AUDIO_DEVICE_NONE) {
2159 bool same_dev = out->devices == new_dev;
2160 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002161
Eric Laurenta7657192014-10-09 21:09:33 -07002162 if (output_drives_call(adev, out)) {
2163 if (!voice_is_in_call(adev)) {
2164 if (adev->mode == AUDIO_MODE_IN_CALL) {
2165 adev->current_call_output = out;
2166 ret = voice_start_call(adev);
2167 }
2168 } else {
2169 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002170 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002171 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002172 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002173
2174 if (!out->standby) {
2175 if (!same_dev) {
2176 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002177 // inform adm before actual routing to prevent glitches.
2178 if (adev->adm_on_routing_change) {
2179 adev->adm_on_routing_change(adev->adm_data,
2180 out->handle);
2181 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002182 }
2183 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002184 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002185 }
2186
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002187 }
2188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002190 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002191
2192 /*handles device and call state changes*/
2193 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002195
2196 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2197 parse_compress_metadata(out, parms);
2198 }
2199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002201 ALOGV("%s: exit: code(%d)", __func__, status);
2202 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203}
2204
Haynes Mathew George569b7482017-05-08 14:44:27 -07002205static bool stream_get_parameter_channels(struct str_parms *query,
2206 struct str_parms *reply,
2207 audio_channel_mask_t *supported_channel_masks) {
2208 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002211 size_t i, j;
2212
2213 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2214 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215 value[0] = '\0';
2216 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002217 while (supported_channel_masks[i] != 0) {
2218 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2219 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 if (!first) {
2221 strcat(value, "|");
2222 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002223 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224 first = false;
2225 break;
2226 }
2227 }
2228 i++;
2229 }
2230 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002231 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002232 return ret >= 0;
2233}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002234
Haynes Mathew George569b7482017-05-08 14:44:27 -07002235static bool stream_get_parameter_formats(struct str_parms *query,
2236 struct str_parms *reply,
2237 audio_format_t *supported_formats) {
2238 int ret = -1;
2239 char value[256];
2240 int i;
2241
2242 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2243 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002244 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002245 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002246 case AUDIO_FORMAT_PCM_16_BIT:
2247 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2248 break;
2249 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2250 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2251 break;
2252 case AUDIO_FORMAT_PCM_32_BIT:
2253 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2254 break;
2255 default:
2256 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002257 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002258 break;
2259 }
2260 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002261 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002262 return ret >= 0;
2263}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002264
Haynes Mathew George569b7482017-05-08 14:44:27 -07002265static bool stream_get_parameter_rates(struct str_parms *query,
2266 struct str_parms *reply,
2267 uint32_t *supported_sample_rates) {
2268
2269 int i;
2270 char value[256];
2271 int ret = -1;
2272 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2273 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002274 value[0] = '\0';
2275 i=0;
2276 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002277 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002278 int avail = sizeof(value) - cursor;
2279 ret = snprintf(value + cursor, avail, "%s%d",
2280 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002281 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002282 if (ret < 0 || ret >= avail) {
2283 // if cursor is at the last element of the array
2284 // overwrite with \0 is duplicate work as
2285 // snprintf already put a \0 in place.
2286 // else
2287 // we had space to write the '|' at value[cursor]
2288 // (which will be overwritten) or no space to fill
2289 // the first element (=> cursor == 0)
2290 value[cursor] = '\0';
2291 break;
2292 }
2293 cursor += ret;
2294 ++i;
2295 }
2296 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2297 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002298 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002299 return ret >= 0;
2300}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002301
Haynes Mathew George569b7482017-05-08 14:44:27 -07002302static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2303{
2304 struct stream_out *out = (struct stream_out *)stream;
2305 struct str_parms *query = str_parms_create_str(keys);
2306 char *str;
2307 struct str_parms *reply = str_parms_create();
2308 bool replied = false;
2309 ALOGV("%s: enter: keys - %s", __func__, keys);
2310
2311 replied |= stream_get_parameter_channels(query, reply,
2312 &out->supported_channel_masks[0]);
2313 replied |= stream_get_parameter_formats(query, reply,
2314 &out->supported_formats[0]);
2315 replied |= stream_get_parameter_rates(query, reply,
2316 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002317 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002318 str = str_parms_to_str(reply);
2319 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002320 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002321 }
2322 str_parms_destroy(query);
2323 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002324 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002325 return str;
2326}
2327
2328static uint32_t out_get_latency(const struct audio_stream_out *stream)
2329{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002330 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 struct stream_out *out = (struct stream_out *)stream;
2332
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002333 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2334 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002335 else if ((out->realtime) ||
2336 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002337 // since the buffer won't be filled up faster than realtime,
2338 // return a smaller number
2339 period_ms = (out->af_period_multiplier * out->config.period_size *
2340 1000) / (out->config.rate);
2341 hw_delay = platform_render_latency(out->usecase)/1000;
2342 return period_ms + hw_delay;
2343 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002344
2345 return (out->config.period_count * out->config.period_size * 1000) /
2346 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002347}
2348
2349static int out_set_volume(struct audio_stream_out *stream, float left,
2350 float right)
2351{
Eric Laurenta9024de2013-04-04 09:19:12 -07002352 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002353 int volume[2];
2354
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002355 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002356 /* only take left channel into account: the API is for stereo anyway */
2357 out->muted = (left == 0.0f);
2358 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2360 const char *mixer_ctl_name = "Compress Playback Volume";
2361 struct audio_device *adev = out->dev;
2362 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2364 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002365 /* try with the control based on device id */
2366 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2367 PCM_PLAYBACK);
2368 char ctl_name[128] = {0};
2369 snprintf(ctl_name, sizeof(ctl_name),
2370 "Compress Playback %d Volume", pcm_device_id);
2371 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2372 if (!ctl) {
2373 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2374 return -EINVAL;
2375 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002376 }
2377 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2378 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2379 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2380 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002381 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002382 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2383 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2384 if (!out->standby) {
2385 // if in standby, cached volume will be sent after stream is opened
2386 audio_extn_utils_send_app_type_gain(out->dev,
2387 out->app_type_cfg.app_type,
2388 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002389 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002390 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002391 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002393 return -ENOSYS;
2394}
2395
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002396// note: this call is safe only if the stream_cb is
2397// removed first in close_output_stream (as is done now).
2398static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2399{
2400 if (!stream || !parms)
2401 return;
2402
2403 struct stream_out *out = (struct stream_out *)stream;
2404 struct audio_device *adev = out->dev;
2405
2406 card_status_t status;
2407 int card;
2408 if (parse_snd_card_status(parms, &card, &status) < 0)
2409 return;
2410
2411 pthread_mutex_lock(&adev->lock);
2412 bool valid_cb = (card == adev->snd_card);
2413 pthread_mutex_unlock(&adev->lock);
2414
2415 if (!valid_cb)
2416 return;
2417
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002418 lock_output_stream(out);
2419 if (out->card_status != status)
2420 out->card_status = status;
2421 pthread_mutex_unlock(&out->lock);
2422
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002423 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2424 use_case_table[out->usecase],
2425 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2426
2427 if (status == CARD_STATUS_OFFLINE)
2428 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002429
2430 return;
2431}
2432
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002433#ifdef NO_AUDIO_OUT
2434static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002435 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002436{
2437 struct stream_out *out = (struct stream_out *)stream;
2438
2439 /* No Output device supported other than BT for playback.
2440 * Sleep for the amount of buffer duration
2441 */
Eric Laurenta1478072015-09-21 17:21:52 -07002442 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002443 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2444 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002445 out_get_sample_rate(&out->stream.common));
2446 pthread_mutex_unlock(&out->lock);
2447 return bytes;
2448}
2449#endif
2450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2452 size_t bytes)
2453{
2454 struct stream_out *out = (struct stream_out *)stream;
2455 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002456 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002457 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458
Eric Laurenta1478072015-09-21 17:21:52 -07002459 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002460 // this is always nonzero
Andy Hung8e7f03f2017-06-12 14:05:22 -07002461 const size_t frame_size = audio_stream_out_frame_size(stream);
2462 const size_t frames = bytes / frame_size;
vivek mehtae3afca22017-04-11 17:13:50 -07002463
Eric Laurent0e46adf2016-12-16 12:49:24 -08002464 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2465 error_code = ERROR_CODE_WRITE;
2466 goto exit;
2467 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002469 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002470 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002471 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002472 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002473 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002475 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002476 goto exit;
2477 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002478
2479 if (last_known_cal_step != -1) {
2480 ALOGD("%s: retry previous failed cal level set", __func__);
2481 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2482 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002485 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002486 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002487 if (out->send_new_metadata) {
2488 ALOGVV("send new gapless metadata");
2489 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2490 out->send_new_metadata = 0;
2491 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002492 unsigned int avail;
2493 struct timespec tstamp;
2494 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2495 /* Do not limit write size if the available frames count is unknown */
2496 if (ret != 0) {
2497 avail = bytes;
2498 }
2499 if (avail == 0) {
2500 ret = 0;
2501 } else {
2502 if (avail > bytes) {
2503 avail = bytes;
2504 }
2505 ret = compress_write(out->compr, buffer, avail);
2506 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2507 __func__, avail, ret);
2508 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002509
Eric Laurent6e895242013-09-05 16:10:57 -07002510 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002511 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2512 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002513 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002514 compress_start(out->compr);
2515 out->playback_started = 1;
2516 out->offload_state = OFFLOAD_STATE_PLAYING;
2517 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002518 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002519 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002520 } else {
2521 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002522 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002523 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002524 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002525 return ret;
2526 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002527 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002528 if (out->pcm) {
2529 if (out->muted)
2530 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002531
Eric Laurent0e46adf2016-12-16 12:49:24 -08002532 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002533
Haynes Mathew George03c40102016-01-29 17:57:48 -08002534 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2535 out->config.rate;
2536 request_out_focus(out, ns);
2537
2538 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2539 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002540 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002541 else
2542 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002543
Haynes Mathew George03c40102016-01-29 17:57:48 -08002544 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002545 } else {
2546 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002547 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548 }
2549
2550exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002551 // For PCM we always consume the buffer and return #bytes regardless of ret.
2552 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07002553 out->written += frames;
Andy Hungda9b56b2016-09-16 20:06:35 -07002554 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002555 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002556
Andy Hung7401c7c2016-09-21 12:41:21 -07002557 if (ret != 0) {
Andy Hung3ba2c922017-06-15 17:48:35 -07002558 error_log_log(out->error_log, error_code, audio_utils_get_real_time_ns());
Andy Hung7401c7c2016-09-21 12:41:21 -07002559 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2560 ALOGE_IF(out->pcm != NULL,
2561 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hung8e7f03f2017-06-12 14:05:22 -07002562 sleeptime_us = frames * 1000000LL / out_get_sample_rate(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002563 // usleep not guaranteed for values over 1 second but we don't limit here.
2564 }
2565 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002566
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002567 pthread_mutex_unlock(&out->lock);
2568
2569 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002570 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002571 if (sleeptime_us != 0)
2572 usleep(sleeptime_us);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 }
2574 return bytes;
2575}
2576
2577static int out_get_render_position(const struct audio_stream_out *stream,
2578 uint32_t *dsp_frames)
2579{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002580 struct stream_out *out = (struct stream_out *)stream;
2581 *dsp_frames = 0;
2582 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002583 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002584 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002585 unsigned long frames = 0;
2586 // TODO: check return value
2587 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2588 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002589 ALOGVV("%s rendered frames %d sample_rate %d",
2590 __func__, *dsp_frames, out->sample_rate);
2591 }
2592 pthread_mutex_unlock(&out->lock);
2593 return 0;
2594 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002595 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596}
2597
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002598static int out_add_audio_effect(const struct audio_stream *stream __unused,
2599 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600{
2601 return 0;
2602}
2603
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002604static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2605 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606{
2607 return 0;
2608}
2609
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002610static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2611 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002613 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614}
2615
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002616static int out_get_presentation_position(const struct audio_stream_out *stream,
2617 uint64_t *frames, struct timespec *timestamp)
2618{
2619 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002620 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002621 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002622
Eric Laurenta1478072015-09-21 17:21:52 -07002623 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002624
Eric Laurent949a0892013-09-20 09:20:13 -07002625 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2626 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002627 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002628 compress_get_tstamp(out->compr, &dsp_frames,
2629 &out->sample_rate);
2630 ALOGVV("%s rendered frames %ld sample_rate %d",
2631 __func__, dsp_frames, out->sample_rate);
2632 *frames = dsp_frames;
2633 ret = 0;
2634 /* this is the best we can do */
2635 clock_gettime(CLOCK_MONOTONIC, timestamp);
2636 }
2637 } else {
2638 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002639 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002640 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2641 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002642 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002643 // This adjustment accounts for buffering after app processor.
2644 // It is based on estimated DSP latency per use case, rather than exact.
2645 signed_frames -=
2646 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2647
Eric Laurent949a0892013-09-20 09:20:13 -07002648 // It would be unusual for this value to be negative, but check just in case ...
2649 if (signed_frames >= 0) {
2650 *frames = signed_frames;
2651 ret = 0;
2652 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002653 }
2654 }
2655 }
2656
2657 pthread_mutex_unlock(&out->lock);
2658
2659 return ret;
2660}
2661
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002662static int out_set_callback(struct audio_stream_out *stream,
2663 stream_callback_t callback, void *cookie)
2664{
2665 struct stream_out *out = (struct stream_out *)stream;
2666
2667 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002668 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002669 out->offload_callback = callback;
2670 out->offload_cookie = cookie;
2671 pthread_mutex_unlock(&out->lock);
2672 return 0;
2673}
2674
2675static int out_pause(struct audio_stream_out* stream)
2676{
2677 struct stream_out *out = (struct stream_out *)stream;
2678 int status = -ENOSYS;
2679 ALOGV("%s", __func__);
2680 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002681 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002682 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2683 status = compress_pause(out->compr);
2684 out->offload_state = OFFLOAD_STATE_PAUSED;
2685 }
2686 pthread_mutex_unlock(&out->lock);
2687 }
2688 return status;
2689}
2690
2691static int out_resume(struct audio_stream_out* stream)
2692{
2693 struct stream_out *out = (struct stream_out *)stream;
2694 int status = -ENOSYS;
2695 ALOGV("%s", __func__);
2696 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2697 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002698 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002699 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2700 status = compress_resume(out->compr);
2701 out->offload_state = OFFLOAD_STATE_PLAYING;
2702 }
2703 pthread_mutex_unlock(&out->lock);
2704 }
2705 return status;
2706}
2707
2708static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2709{
2710 struct stream_out *out = (struct stream_out *)stream;
2711 int status = -ENOSYS;
2712 ALOGV("%s", __func__);
2713 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002714 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002715 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2716 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2717 else
2718 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2719 pthread_mutex_unlock(&out->lock);
2720 }
2721 return status;
2722}
2723
2724static int out_flush(struct audio_stream_out* stream)
2725{
2726 struct stream_out *out = (struct stream_out *)stream;
2727 ALOGV("%s", __func__);
2728 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002729 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002730 stop_compressed_output_l(out);
2731 pthread_mutex_unlock(&out->lock);
2732 return 0;
2733 }
2734 return -ENOSYS;
2735}
2736
Eric Laurent0e46adf2016-12-16 12:49:24 -08002737static int out_stop(const struct audio_stream_out* stream)
2738{
2739 struct stream_out *out = (struct stream_out *)stream;
2740 struct audio_device *adev = out->dev;
2741 int ret = -ENOSYS;
2742
2743 ALOGV("%s", __func__);
2744 pthread_mutex_lock(&adev->lock);
2745 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2746 out->playback_started && out->pcm != NULL) {
2747 pcm_stop(out->pcm);
2748 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002749 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002750 }
2751 pthread_mutex_unlock(&adev->lock);
2752 return ret;
2753}
2754
2755static int out_start(const struct audio_stream_out* stream)
2756{
2757 struct stream_out *out = (struct stream_out *)stream;
2758 struct audio_device *adev = out->dev;
2759 int ret = -ENOSYS;
2760
2761 ALOGV("%s", __func__);
2762 pthread_mutex_lock(&adev->lock);
2763 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2764 !out->playback_started && out->pcm != NULL) {
2765 ret = start_output_stream(out);
2766 if (ret == 0) {
2767 out->playback_started = true;
2768 }
2769 }
2770 pthread_mutex_unlock(&adev->lock);
2771 return ret;
2772}
2773
Phil Burkbc991042017-02-24 08:06:44 -08002774/*
2775 * Modify config->period_count based on min_size_frames
2776 */
2777static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2778{
2779 int periodCountRequested = (min_size_frames + config->period_size - 1)
2780 / config->period_size;
2781 int periodCount = MMAP_PERIOD_COUNT_MIN;
2782
2783 ALOGV("%s original config.period_size = %d config.period_count = %d",
2784 __func__, config->period_size, config->period_count);
2785
2786 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2787 periodCount *= 2;
2788 }
2789 config->period_count = periodCount;
2790
2791 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2792}
2793
Eric Laurent0e46adf2016-12-16 12:49:24 -08002794static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2795 int32_t min_size_frames,
2796 struct audio_mmap_buffer_info *info)
2797{
2798 struct stream_out *out = (struct stream_out *)stream;
2799 struct audio_device *adev = out->dev;
2800 int ret = 0;
2801 unsigned int offset1;
2802 unsigned int frames1;
2803 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002804 uint32_t mmap_size;
2805 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002806
2807 ALOGV("%s", __func__);
2808 pthread_mutex_lock(&adev->lock);
2809
2810 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002811 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002812 ret = -EINVAL;
2813 goto exit;
2814 }
2815 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002816 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002817 ret = -ENOSYS;
2818 goto exit;
2819 }
2820 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2821 if (out->pcm_device_id < 0) {
2822 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2823 __func__, out->pcm_device_id, out->usecase);
2824 ret = -EINVAL;
2825 goto exit;
2826 }
Phil Burkbc991042017-02-24 08:06:44 -08002827
2828 adjust_mmap_period_count(&out->config, min_size_frames);
2829
Eric Laurent0e46adf2016-12-16 12:49:24 -08002830 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2831 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2832 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2833 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2834 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2835 step = "open";
2836 ret = -ENODEV;
2837 goto exit;
2838 }
2839 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2840 if (ret < 0) {
2841 step = "begin";
2842 goto exit;
2843 }
2844 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002845 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002846 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002847 ret = platform_get_mmap_data_fd(adev->platform,
2848 out->pcm_device_id, 0 /*playback*/,
2849 &info->shared_memory_fd,
2850 &mmap_size);
2851 if (ret < 0) {
2852 // Fall back to non exclusive mode
2853 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2854 } else {
2855 if (mmap_size < buffer_size) {
2856 step = "mmap";
2857 goto exit;
2858 }
2859 // FIXME: indicate exclusive mode support by returning a negative buffer size
2860 info->buffer_size_frames *= -1;
2861 }
2862 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002863
2864 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2865 if (ret < 0) {
2866 step = "commit";
2867 goto exit;
2868 }
Phil Burkbc991042017-02-24 08:06:44 -08002869
2870 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002871 ret = 0;
2872
2873 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2874 __func__, info->shared_memory_address, info->buffer_size_frames);
2875
2876exit:
2877 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002878 if (out->pcm == NULL) {
2879 ALOGE("%s: %s - %d", __func__, step, ret);
2880 } else {
2881 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002882 pcm_close(out->pcm);
2883 out->pcm = NULL;
2884 }
2885 }
2886 pthread_mutex_unlock(&adev->lock);
2887 return ret;
2888}
2889
2890static int out_get_mmap_position(const struct audio_stream_out *stream,
2891 struct audio_mmap_position *position)
2892{
2893 struct stream_out *out = (struct stream_out *)stream;
2894 ALOGVV("%s", __func__);
2895 if (position == NULL) {
2896 return -EINVAL;
2897 }
2898 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2899 return -ENOSYS;
2900 }
2901 if (out->pcm == NULL) {
2902 return -ENOSYS;
2903 }
2904
2905 struct timespec ts = { 0, 0 };
2906 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2907 if (ret < 0) {
2908 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2909 return ret;
2910 }
Andy Hungfc044e12017-03-20 09:24:22 -07002911 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002912 return 0;
2913}
2914
2915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916/** audio_stream_in implementation **/
2917static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2918{
2919 struct stream_in *in = (struct stream_in *)stream;
2920
2921 return in->config.rate;
2922}
2923
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002924static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002925{
2926 return -ENOSYS;
2927}
2928
2929static size_t in_get_buffer_size(const struct audio_stream *stream)
2930{
2931 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002932 return in->config.period_size * in->af_period_multiplier *
2933 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934}
2935
2936static uint32_t in_get_channels(const struct audio_stream *stream)
2937{
2938 struct stream_in *in = (struct stream_in *)stream;
2939
2940 return in->channel_mask;
2941}
2942
vivek mehta4ed66e62016-04-15 23:33:34 -07002943static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944{
vivek mehta4ed66e62016-04-15 23:33:34 -07002945 struct stream_in *in = (struct stream_in *)stream;
2946 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947}
2948
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002949static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950{
2951 return -ENOSYS;
2952}
2953
2954static int in_standby(struct audio_stream *stream)
2955{
2956 struct stream_in *in = (struct stream_in *)stream;
2957 struct audio_device *adev = in->dev;
2958 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002959 bool do_stop = true;
2960
Eric Laurent994a6932013-07-17 11:51:42 -07002961 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002962
2963 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002964
2965 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002966 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002967 audio_extn_sound_trigger_stop_lab(in);
2968 in->standby = true;
2969 }
2970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002971 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002972 if (adev->adm_deregister_stream)
2973 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2974
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002975 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002977 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002978 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002979 in->capture_started = false;
2980 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002981 if (in->pcm) {
2982 pcm_close(in->pcm);
2983 in->pcm = NULL;
2984 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002985 adev->enable_voicerx = false;
2986 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002987 if (do_stop) {
2988 status = stop_input_stream(in);
2989 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002990 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991 }
2992 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002993 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 return status;
2995}
2996
Andy Hungd13f0d32017-06-12 13:58:37 -07002997static int in_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998{
Andy Hungd13f0d32017-06-12 13:58:37 -07002999 struct stream_in *in = (struct stream_in *)stream;
3000
3001 // We try to get the lock for consistency,
3002 // but it isn't necessary for these variables.
3003 // If we're not in standby, we may be blocked on a read.
3004 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
3005 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
3006 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
3007 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
3008
3009 if (locked) {
3010 pthread_mutex_unlock(&in->lock);
3011 }
3012
3013 // dump error info
3014 (void)error_log_dump(
3015 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 return 0;
3017}
3018
3019static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3020{
3021 struct stream_in *in = (struct stream_in *)stream;
3022 struct audio_device *adev = in->dev;
3023 struct str_parms *parms;
3024 char *str;
3025 char value[32];
3026 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003027 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028
Eric Laurent994a6932013-07-17 11:51:42 -07003029 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 parms = str_parms_create_str(kvpairs);
3031
3032 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3033
Eric Laurenta1478072015-09-21 17:21:52 -07003034 lock_input_stream(in);
3035
Eric Laurent150dbfe2013-02-27 14:31:02 -08003036 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 if (ret >= 0) {
3038 val = atoi(value);
3039 /* no audio source uses val == 0 */
3040 if ((in->source != val) && (val != 0)) {
3041 in->source = val;
3042 }
3043 }
3044
3045 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003046
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047 if (ret >= 0) {
3048 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003049 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 in->device = val;
3051 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003052 if (!in->standby) {
3053 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003054 // inform adm before actual routing to prevent glitches.
3055 if (adev->adm_on_routing_change) {
3056 adev->adm_on_routing_change(adev->adm_data,
3057 in->capture_handle);
3058 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003059 select_devices(adev, in->usecase);
3060 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003061 }
3062 }
3063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003064 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003065 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066
3067 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003068 ALOGV("%s: exit: status(%d)", __func__, status);
3069 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003070}
3071
Haynes Mathew George569b7482017-05-08 14:44:27 -07003072static char* in_get_parameters(const struct audio_stream *stream,
3073 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003075 struct stream_in *in = (struct stream_in *)stream;
3076 struct str_parms *query = str_parms_create_str(keys);
3077 char *str;
3078 struct str_parms *reply = str_parms_create();
3079 bool replied = false;
3080
3081 ALOGV("%s: enter: keys - %s", __func__, keys);
3082 replied |= stream_get_parameter_channels(query, reply,
3083 &in->supported_channel_masks[0]);
3084 replied |= stream_get_parameter_formats(query, reply,
3085 &in->supported_formats[0]);
3086 replied |= stream_get_parameter_rates(query, reply,
3087 &in->supported_sample_rates[0]);
3088 if (replied) {
3089 str = str_parms_to_str(reply);
3090 } else {
3091 str = strdup(keys);
3092 }
3093 str_parms_destroy(query);
3094 str_parms_destroy(reply);
3095 ALOGV("%s: exit: returns - %s", __func__, str);
3096 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097}
3098
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003099static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003100{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003101 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102}
3103
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003104static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3105{
3106 if (!stream || !parms)
3107 return;
3108
3109 struct stream_in *in = (struct stream_in *)stream;
3110 struct audio_device *adev = in->dev;
3111
3112 card_status_t status;
3113 int card;
3114 if (parse_snd_card_status(parms, &card, &status) < 0)
3115 return;
3116
3117 pthread_mutex_lock(&adev->lock);
3118 bool valid_cb = (card == adev->snd_card);
3119 pthread_mutex_unlock(&adev->lock);
3120
3121 if (!valid_cb)
3122 return;
3123
3124 lock_input_stream(in);
3125 if (in->card_status != status)
3126 in->card_status = status;
3127 pthread_mutex_unlock(&in->lock);
3128
3129 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3130 use_case_table[in->usecase],
3131 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3132
3133 // a better solution would be to report error back to AF and let
3134 // it put the stream to standby
3135 if (status == CARD_STATUS_OFFLINE)
3136 in_standby(&in->stream.common);
3137
3138 return;
3139}
3140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3142 size_t bytes)
3143{
3144 struct stream_in *in = (struct stream_in *)stream;
3145 struct audio_device *adev = in->dev;
3146 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003147 int *int_buf_stream = NULL;
Andy Hungd13f0d32017-06-12 13:58:37 -07003148 int error_code = ERROR_CODE_STANDBY; // initial errors are considered coming out of standby.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149
Eric Laurenta1478072015-09-21 17:21:52 -07003150 lock_input_stream(in);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003151 const size_t frame_size = audio_stream_in_frame_size(stream);
3152 const size_t frames = bytes / frame_size;
Eric Laurenta1478072015-09-21 17:21:52 -07003153
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003154 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003155 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003156 /* Read from sound trigger HAL */
3157 audio_extn_sound_trigger_read(in, buffer, bytes);
3158 pthread_mutex_unlock(&in->lock);
3159 return bytes;
3160 }
3161
Eric Laurent0e46adf2016-12-16 12:49:24 -08003162 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3163 ret = -ENOSYS;
3164 goto exit;
3165 }
3166
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003167 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003168 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003170 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003171 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172 goto exit;
3173 }
3174 in->standby = 0;
3175 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176
Andy Hungd13f0d32017-06-12 13:58:37 -07003177 // errors that occur here are read errors.
3178 error_code = ERROR_CODE_READ;
3179
Haynes Mathew George03c40102016-01-29 17:57:48 -08003180 //what's the duration requested by the client?
3181 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3182 in->config.rate;
3183 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003184
Haynes Mathew George03c40102016-01-29 17:57:48 -08003185 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003186 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003187 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003188 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003189 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003190 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003191 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003192 if (ret < 0) {
3193 ALOGE("Failed to read w/err %s", strerror(errno));
3194 ret = -errno;
3195 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003196 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3197 if (bytes % 4 == 0) {
3198 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3199 int_buf_stream = buffer;
3200 for (size_t itt=0; itt < bytes/4 ; itt++) {
3201 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003202 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003203 } else {
3204 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3205 ret = -EINVAL;
3206 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003207 }
3208 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003209 }
3210
Haynes Mathew George03c40102016-01-29 17:57:48 -08003211 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 /*
3214 * Instead of writing zeroes here, we could trust the hardware
3215 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003216 * 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 -08003217 */
Andy Hungd13f0d32017-06-12 13:58:37 -07003218 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 memset(buffer, 0, bytes);
Andy Hungd13f0d32017-06-12 13:58:37 -07003220 in->frames_muted += frames;
3221 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222
3223exit:
3224 pthread_mutex_unlock(&in->lock);
3225
3226 if (ret != 0) {
Andy Hungd13f0d32017-06-12 13:58:37 -07003227 error_log_log(in->error_log, error_code, audio_utils_get_real_time_ns());
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228 in_standby(&in->stream.common);
3229 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Andy Hung8e7f03f2017-06-12 14:05:22 -07003230 usleep(frames * 1000000LL / in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003231 memset(buffer, 0, bytes); // clear return data
Andy Hungd13f0d32017-06-12 13:58:37 -07003232 in->frames_muted += frames;
Andy Hungc8589872016-03-10 16:37:48 -08003233 }
3234 if (bytes > 0) {
Andy Hung8e7f03f2017-06-12 14:05:22 -07003235 in->frames_read += frames;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003236 }
3237 return bytes;
3238}
3239
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003240static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003241{
3242 return 0;
3243}
3244
Andy Hung6ebe5962016-01-15 17:46:57 -08003245static int in_get_capture_position(const struct audio_stream_in *stream,
3246 int64_t *frames, int64_t *time)
3247{
3248 if (stream == NULL || frames == NULL || time == NULL) {
3249 return -EINVAL;
3250 }
3251 struct stream_in *in = (struct stream_in *)stream;
3252 int ret = -ENOSYS;
3253
3254 lock_input_stream(in);
3255 if (in->pcm) {
3256 struct timespec timestamp;
3257 unsigned int avail;
3258 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3259 *frames = in->frames_read + avail;
3260 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3261 ret = 0;
3262 }
3263 }
3264 pthread_mutex_unlock(&in->lock);
3265 return ret;
3266}
3267
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003268static int add_remove_audio_effect(const struct audio_stream *stream,
3269 effect_handle_t effect,
3270 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003271{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003272 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003273 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003274 int status = 0;
3275 effect_descriptor_t desc;
3276
3277 status = (*effect)->get_descriptor(effect, &desc);
3278 if (status != 0)
3279 return status;
3280
Eric Laurenta1478072015-09-21 17:21:52 -07003281 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003282 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003283 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003284 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003285 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003286 in->enable_aec != enable &&
3287 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3288 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003289 if (!enable)
3290 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003291 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3292 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3293 adev->enable_voicerx = enable;
3294 struct audio_usecase *usecase;
3295 struct listnode *node;
3296 list_for_each(node, &adev->usecase_list) {
3297 usecase = node_to_item(node, struct audio_usecase, list);
3298 if (usecase->type == PCM_PLAYBACK) {
3299 select_devices(adev, usecase->id);
3300 break;
3301 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003302 }
3303 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003304 if (!in->standby)
3305 select_devices(in->dev, in->usecase);
3306 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003307 if (in->enable_ns != enable &&
3308 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3309 in->enable_ns = enable;
3310 if (!in->standby)
3311 select_devices(in->dev, in->usecase);
3312 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003313 pthread_mutex_unlock(&in->dev->lock);
3314 pthread_mutex_unlock(&in->lock);
3315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316 return 0;
3317}
3318
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003319static int in_add_audio_effect(const struct audio_stream *stream,
3320 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003321{
Eric Laurent994a6932013-07-17 11:51:42 -07003322 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003323 return add_remove_audio_effect(stream, effect, true);
3324}
3325
3326static int in_remove_audio_effect(const struct audio_stream *stream,
3327 effect_handle_t effect)
3328{
Eric Laurent994a6932013-07-17 11:51:42 -07003329 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003330 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331}
3332
Eric Laurent0e46adf2016-12-16 12:49:24 -08003333static int in_stop(const struct audio_stream_in* stream)
3334{
3335 struct stream_in *in = (struct stream_in *)stream;
3336 struct audio_device *adev = in->dev;
3337
3338 int ret = -ENOSYS;
3339 ALOGV("%s", __func__);
3340 pthread_mutex_lock(&adev->lock);
3341 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3342 in->capture_started && in->pcm != NULL) {
3343 pcm_stop(in->pcm);
3344 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003345 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003346 }
3347 pthread_mutex_unlock(&adev->lock);
3348 return ret;
3349}
3350
3351static int in_start(const struct audio_stream_in* stream)
3352{
3353 struct stream_in *in = (struct stream_in *)stream;
3354 struct audio_device *adev = in->dev;
3355 int ret = -ENOSYS;
3356
3357 ALOGV("%s in %p", __func__, in);
3358 pthread_mutex_lock(&adev->lock);
3359 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3360 !in->capture_started && in->pcm != NULL) {
3361 if (!in->capture_started) {
3362 ret = start_input_stream(in);
3363 if (ret == 0) {
3364 in->capture_started = true;
3365 }
3366 }
3367 }
3368 pthread_mutex_unlock(&adev->lock);
3369 return ret;
3370}
3371
3372static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3373 int32_t min_size_frames,
3374 struct audio_mmap_buffer_info *info)
3375{
3376 struct stream_in *in = (struct stream_in *)stream;
3377 struct audio_device *adev = in->dev;
3378 int ret = 0;
3379 unsigned int offset1;
3380 unsigned int frames1;
3381 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003382 uint32_t mmap_size;
3383 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003384
3385 pthread_mutex_lock(&adev->lock);
3386 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003387
Eric Laurent0e46adf2016-12-16 12:49:24 -08003388 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003389 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003390 ret = -EINVAL;
3391 goto exit;
3392 }
3393 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003394 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003395 ALOGV("%s in %p", __func__, in);
3396 ret = -ENOSYS;
3397 goto exit;
3398 }
3399 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3400 if (in->pcm_device_id < 0) {
3401 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3402 __func__, in->pcm_device_id, in->usecase);
3403 ret = -EINVAL;
3404 goto exit;
3405 }
Phil Burkbc991042017-02-24 08:06:44 -08003406
3407 adjust_mmap_period_count(&in->config, min_size_frames);
3408
Eric Laurent0e46adf2016-12-16 12:49:24 -08003409 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3410 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3411 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3412 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3413 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3414 step = "open";
3415 ret = -ENODEV;
3416 goto exit;
3417 }
3418
3419 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3420 if (ret < 0) {
3421 step = "begin";
3422 goto exit;
3423 }
3424 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003425 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003426 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003427 ret = platform_get_mmap_data_fd(adev->platform,
3428 in->pcm_device_id, 1 /*capture*/,
3429 &info->shared_memory_fd,
3430 &mmap_size);
3431 if (ret < 0) {
3432 // Fall back to non exclusive mode
3433 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3434 } else {
3435 if (mmap_size < buffer_size) {
3436 step = "mmap";
3437 goto exit;
3438 }
3439 // FIXME: indicate exclusive mode support by returning a negative buffer size
3440 info->buffer_size_frames *= -1;
3441 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003442
Haynes Mathew George96483a22017-03-28 14:52:47 -07003443 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003444
3445 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3446 if (ret < 0) {
3447 step = "commit";
3448 goto exit;
3449 }
3450
Phil Burkbc991042017-02-24 08:06:44 -08003451 in->standby = false;
3452 ret = 0;
3453
Eric Laurent0e46adf2016-12-16 12:49:24 -08003454 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3455 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003456
3457exit:
3458 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003459 if (in->pcm == NULL) {
3460 ALOGE("%s: %s - %d", __func__, step, ret);
3461 } else {
3462 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003463 pcm_close(in->pcm);
3464 in->pcm = NULL;
3465 }
3466 }
3467 pthread_mutex_unlock(&adev->lock);
3468 return ret;
3469}
3470
3471static int in_get_mmap_position(const struct audio_stream_in *stream,
3472 struct audio_mmap_position *position)
3473{
3474 struct stream_in *in = (struct stream_in *)stream;
3475 ALOGVV("%s", __func__);
3476 if (position == NULL) {
3477 return -EINVAL;
3478 }
3479 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3480 return -ENOSYS;
3481 }
3482 if (in->pcm == NULL) {
3483 return -ENOSYS;
3484 }
3485 struct timespec ts = { 0, 0 };
3486 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3487 if (ret < 0) {
3488 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3489 return ret;
3490 }
Andy Hungfc044e12017-03-20 09:24:22 -07003491 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003492 return 0;
3493}
3494
3495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003496static int adev_open_output_stream(struct audio_hw_device *dev,
3497 audio_io_handle_t handle,
3498 audio_devices_t devices,
3499 audio_output_flags_t flags,
3500 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003501 struct audio_stream_out **stream_out,
3502 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003503{
3504 struct audio_device *adev = (struct audio_device *)dev;
3505 struct stream_out *out;
3506 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003507 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3508 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3509 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3510 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003511
Eric Laurent994a6932013-07-17 11:51:42 -07003512 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003513 __func__, config->sample_rate, config->channel_mask, devices, flags);
3514 *stream_out = NULL;
3515 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3516
3517 if (devices == AUDIO_DEVICE_NONE)
3518 devices = AUDIO_DEVICE_OUT_SPEAKER;
3519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520 out->flags = flags;
3521 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003522 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003523 out->format = config->format;
3524 out->sample_rate = config->sample_rate;
3525 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3526 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003527 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528
3529 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003530 if (audio_is_linear_pcm(out->format) &&
3531 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003532 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003533 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003534 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003535 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003536 if (config->sample_rate == 0)
3537 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3538 if (config->channel_mask == 0)
3539 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3540 if (config->format == AUDIO_FORMAT_DEFAULT)
3541 config->format = AUDIO_FORMAT_PCM_16_BIT;
3542 } else if (is_usb_dev) {
3543 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3544 &config->format,
3545 &out->supported_formats[0],
3546 MAX_SUPPORTED_FORMATS,
3547 &config->channel_mask,
3548 &out->supported_channel_masks[0],
3549 MAX_SUPPORTED_CHANNEL_MASKS,
3550 &config->sample_rate,
3551 &out->supported_sample_rates[0],
3552 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003553 ALOGV("plugged dev USB ret %d", ret);
3554 } else {
3555 ret = -1;
3556 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003557 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003558 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003559 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003560
Haynes Mathew George569b7482017-05-08 14:44:27 -07003561 out->channel_mask = config->channel_mask;
3562 out->sample_rate = config->sample_rate;
3563 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003564 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3565 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003566 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003568 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003569 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003570 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003571 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003572 pthread_mutex_lock(&adev->lock);
3573 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3574 pthread_mutex_unlock(&adev->lock);
3575
3576 // reject offload during card offline to allow
3577 // fallback to s/w paths
3578 if (offline) {
3579 ret = -ENODEV;
3580 goto error_open;
3581 }
3582
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003583 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3584 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3585 ALOGE("%s: Unsupported Offload information", __func__);
3586 ret = -EINVAL;
3587 goto error_open;
3588 }
3589 if (!is_supported_format(config->offload_info.format)) {
3590 ALOGE("%s: Unsupported audio format", __func__);
3591 ret = -EINVAL;
3592 goto error_open;
3593 }
3594
3595 out->compr_config.codec = (struct snd_codec *)
3596 calloc(1, sizeof(struct snd_codec));
3597
3598 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3599 if (config->offload_info.channel_mask)
3600 out->channel_mask = config->offload_info.channel_mask;
3601 else if (config->channel_mask)
3602 out->channel_mask = config->channel_mask;
3603 out->format = config->offload_info.format;
3604 out->sample_rate = config->offload_info.sample_rate;
3605
3606 out->stream.set_callback = out_set_callback;
3607 out->stream.pause = out_pause;
3608 out->stream.resume = out_resume;
3609 out->stream.drain = out_drain;
3610 out->stream.flush = out_flush;
3611
3612 out->compr_config.codec->id =
3613 get_snd_codec_id(config->offload_info.format);
3614 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3615 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003616 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003617 out->compr_config.codec->bit_rate =
3618 config->offload_info.bit_rate;
3619 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003620 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003621 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3622
3623 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3624 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003625
3626 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003627 create_offload_callback_thread(out);
3628 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3629 __func__, config->offload_info.version,
3630 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003631 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003632 switch (config->sample_rate) {
3633 case 8000:
3634 case 16000:
3635 case 48000:
3636 out->sample_rate = config->sample_rate;
3637 break;
3638 default:
3639 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003640 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003641 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003642 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3643 out->config = pcm_config_afe_proxy_playback;
3644 adev->voice_tx_output = out;
vivek mehtaa68fea62017-06-08 19:04:02 -07003645 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3646 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3647 AUDIO_OUTPUT_FLAG_VOIP_RX))) {
3648 uint32_t buffer_size, frame_size;
3649 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3650 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3651 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3652 out->config = pcm_config_voip;
3653 out->config.format = pcm_format_from_audio_format(config->format);
3654 out->config.rate = config->sample_rate;
3655 out->config.channels =
3656 audio_channel_count_from_out_mask(config->channel_mask);
3657 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3658 config->sample_rate,
3659 config->format,
3660 out->config.channels,
3661 false /*is_low_latency*/);
3662 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3663 out->config.period_size = buffer_size / frame_size;
3664 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3665 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003667 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3668 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3669 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003670 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3671 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3672 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003673 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3674 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003675 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003676 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003677 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3678 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3679 out->config = pcm_config_mmap_playback;
3680 out->stream.start = out_start;
3681 out->stream.stop = out_stop;
3682 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3683 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003684 } else {
3685 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3686 out->config = pcm_config_low_latency;
3687 }
3688 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3689 if (k_enable_extended_precision
3690 && pcm_params_format_test(adev->use_case_table[out->usecase],
3691 pcm_format_from_audio_format(config->format))) {
3692 out->config.format = pcm_format_from_audio_format(config->format);
3693 /* out->format already set to config->format */
3694 } else {
3695 /* deny the externally proposed config format
3696 * and use the one specified in audio_hw layer configuration.
3697 * Note: out->format is returned by out->stream.common.get_format()
3698 * and is used to set config->format in the code several lines below.
3699 */
3700 out->format = audio_format_from_pcm_format(out->config.format);
3701 }
3702 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003703 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003705
3706 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3707 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3708 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3709 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3710 __func__, config->sample_rate, config->format, config->channel_mask);
3711 config->sample_rate = out->sample_rate;
3712 config->format = out->format;
3713 config->channel_mask = out->channel_mask;
3714 ret = -EINVAL;
3715 goto error_open;
3716 }
3717
Andy Hung6fcba9c2014-03-18 11:53:32 -07003718 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3719 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003721 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003722 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003723 adev->primary_output = out;
3724 else {
3725 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003726 ret = -EEXIST;
3727 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003728 }
3729 }
3730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003731 /* Check if this usecase is already existing */
3732 pthread_mutex_lock(&adev->lock);
3733 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3734 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003736 ret = -EEXIST;
3737 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 }
3739 pthread_mutex_unlock(&adev->lock);
3740
3741 out->stream.common.get_sample_rate = out_get_sample_rate;
3742 out->stream.common.set_sample_rate = out_set_sample_rate;
3743 out->stream.common.get_buffer_size = out_get_buffer_size;
3744 out->stream.common.get_channels = out_get_channels;
3745 out->stream.common.get_format = out_get_format;
3746 out->stream.common.set_format = out_set_format;
3747 out->stream.common.standby = out_standby;
3748 out->stream.common.dump = out_dump;
3749 out->stream.common.set_parameters = out_set_parameters;
3750 out->stream.common.get_parameters = out_get_parameters;
3751 out->stream.common.add_audio_effect = out_add_audio_effect;
3752 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3753 out->stream.get_latency = out_get_latency;
3754 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003755#ifdef NO_AUDIO_OUT
3756 out->stream.write = out_write_for_no_output;
3757#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003759#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 out->stream.get_render_position = out_get_render_position;
3761 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003762 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763
Eric Laurent0e46adf2016-12-16 12:49:24 -08003764 if (out->realtime)
3765 out->af_period_multiplier = af_period_multiplier;
3766 else
3767 out->af_period_multiplier = 1;
3768
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003770 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003771 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003773 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003774 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003775 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777 config->format = out->stream.common.get_format(&out->stream.common);
3778 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3779 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3780
Andy Hunga452b0a2017-03-15 14:51:15 -07003781 out->error_log = error_log_create(
3782 ERROR_LOG_ENTRIES,
3783 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3784
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003785 /*
3786 By locking output stream before registering, we allow the callback
3787 to update stream's state only after stream's initial state is set to
3788 adev state.
3789 */
3790 lock_output_stream(out);
3791 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3792 pthread_mutex_lock(&adev->lock);
3793 out->card_status = adev->card_status;
3794 pthread_mutex_unlock(&adev->lock);
3795 pthread_mutex_unlock(&out->lock);
3796
vivek mehta4a824772017-06-08 19:05:49 -07003797 stream_app_type_cfg_init(&out->app_type_cfg);
3798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003799 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003800
Eric Laurent994a6932013-07-17 11:51:42 -07003801 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003802 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003803
3804error_open:
3805 free(out);
3806 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003807 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003808 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003809}
3810
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003811static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812 struct audio_stream_out *stream)
3813{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814 struct stream_out *out = (struct stream_out *)stream;
3815 struct audio_device *adev = out->dev;
3816
Eric Laurent994a6932013-07-17 11:51:42 -07003817 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003818
3819 // must deregister from sndmonitor first to prevent races
3820 // between the callback and close_stream
3821 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003823 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3824 destroy_offload_callback_thread(out);
3825
3826 if (out->compr_config.codec != NULL)
3827 free(out->compr_config.codec);
3828 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003829
3830 if (adev->voice_tx_output == out)
3831 adev->voice_tx_output = NULL;
3832
Andy Hunga452b0a2017-03-15 14:51:15 -07003833 error_log_destroy(out->error_log);
3834 out->error_log = NULL;
3835
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003836 pthread_cond_destroy(&out->cond);
3837 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003839 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840}
3841
3842static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3843{
3844 struct audio_device *adev = (struct audio_device *)dev;
3845 struct str_parms *parms;
3846 char *str;
3847 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003848 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003850 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003851
Joe Onorato188b6222016-03-01 11:02:27 -08003852 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003853
3854 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855
3856 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003857 status = voice_set_parameters(adev, parms);
3858 if (status != 0) {
3859 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003860 }
3861
3862 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3863 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003864 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003865 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3866 adev->bluetooth_nrec = true;
3867 else
3868 adev->bluetooth_nrec = false;
3869 }
3870
3871 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3872 if (ret >= 0) {
3873 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3874 adev->screen_off = false;
3875 else
3876 adev->screen_off = true;
3877 }
3878
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003879 ret = str_parms_get_int(parms, "rotation", &val);
3880 if (ret >= 0) {
3881 bool reverse_speakers = false;
3882 switch(val) {
3883 // FIXME: note that the code below assumes that the speakers are in the correct placement
3884 // relative to the user when the device is rotated 90deg from its default rotation. This
3885 // assumption is device-specific, not platform-specific like this code.
3886 case 270:
3887 reverse_speakers = true;
3888 break;
3889 case 0:
3890 case 90:
3891 case 180:
3892 break;
3893 default:
3894 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003895 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003896 }
Eric Laurent03f09432014-03-25 18:09:11 -07003897 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003898 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003899 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003900 }
3901
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003902 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3903 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003904 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003905 }
3906
David Linee3fe402017-03-13 10:00:42 -07003907 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3908 if (ret >= 0) {
3909 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003910 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003911 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3912 if (ret >= 0) {
3913 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003914 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003915 }
Eric Laurent99dab492017-06-17 15:19:08 -07003916 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003917 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3918 if (ret >= 0) {
3919 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003920 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003921 }
3922 }
3923 }
3924
3925 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3926 if (ret >= 0) {
3927 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003928 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003929 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3930 if (ret >= 0) {
3931 const int card = atoi(value);
3932
Eric Laurent99dab492017-06-17 15:19:08 -07003933 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003934 }
Eric Laurent99dab492017-06-17 15:19:08 -07003935 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003936 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3937 if (ret >= 0) {
3938 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003939 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003940 }
3941 }
3942 }
3943
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003944 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003945done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003947 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003948 ALOGV("%s: exit with code(%d)", __func__, status);
3949 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003950}
3951
3952static char* adev_get_parameters(const struct audio_hw_device *dev,
3953 const char *keys)
3954{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003955 struct audio_device *adev = (struct audio_device *)dev;
3956 struct str_parms *reply = str_parms_create();
3957 struct str_parms *query = str_parms_create_str(keys);
3958 char *str;
3959
3960 pthread_mutex_lock(&adev->lock);
3961
3962 voice_get_parameters(adev, query, reply);
3963 str = str_parms_to_str(reply);
3964 str_parms_destroy(query);
3965 str_parms_destroy(reply);
3966
3967 pthread_mutex_unlock(&adev->lock);
3968 ALOGV("%s: exit: returns - %s", __func__, str);
3969 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970}
3971
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003972static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003973{
3974 return 0;
3975}
3976
Haynes Mathew George5191a852013-09-11 14:19:36 -07003977static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3978{
3979 int ret;
3980 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003981
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003982 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3983
Haynes Mathew George5191a852013-09-11 14:19:36 -07003984 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003985 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003986 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003987
Haynes Mathew George5191a852013-09-11 14:19:36 -07003988 return ret;
3989}
3990
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003991static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992{
3993 return -ENOSYS;
3994}
3995
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003996static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3997 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003998{
3999 return -ENOSYS;
4000}
4001
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004002static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004003{
4004 return -ENOSYS;
4005}
4006
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004007static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008{
4009 return -ENOSYS;
4010}
4011
4012static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4013{
4014 struct audio_device *adev = (struct audio_device *)dev;
4015
4016 pthread_mutex_lock(&adev->lock);
4017 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004018 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004019 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004020 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4021 voice_is_in_call(adev)) {
4022 voice_stop_call(adev);
4023 adev->current_call_output = NULL;
4024 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004025 }
4026 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004027
4028 audio_extn_extspk_set_mode(adev->extspk, mode);
4029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004030 return 0;
4031}
4032
4033static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4034{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004035 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004036 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004037
Eric Laurent2bafff12016-03-17 12:17:23 -07004038 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004039 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004040 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4041 ret = audio_extn_hfp_set_mic_mute(adev, state);
4042 } else {
4043 ret = voice_set_mic_mute(adev, state);
4044 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004045 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004046 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004047
4048 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004049}
4050
4051static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4052{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004053 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054 return 0;
4055}
4056
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004057static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004058 const struct audio_config *config)
4059{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004060 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004061
vivek mehtaa68fea62017-06-08 19:04:02 -07004062 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4063 config->sample_rate, config->format,
4064 channel_count,
4065 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004066}
4067
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004068static bool adev_input_allow_hifi_record(struct audio_device *adev,
4069 audio_devices_t devices,
4070 audio_input_flags_t flags,
4071 audio_source_t source) {
4072 const bool allowed = true;
4073
4074 if (!audio_is_usb_in_device(devices))
4075 return !allowed;
4076
4077 switch (flags) {
4078 case AUDIO_INPUT_FLAG_NONE:
4079 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4080 break;
4081 default:
4082 return !allowed;
4083 }
4084
4085 switch (source) {
4086 case AUDIO_SOURCE_DEFAULT:
4087 case AUDIO_SOURCE_MIC:
4088 case AUDIO_SOURCE_UNPROCESSED:
4089 break;
4090 default:
4091 return !allowed;
4092 }
4093
4094 switch (adev->mode) {
4095 case 0:
4096 break;
4097 default:
4098 return !allowed;
4099 }
4100
4101 return allowed;
4102}
4103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004104static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004105 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004106 audio_devices_t devices,
4107 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004108 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004109 audio_input_flags_t flags,
4110 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004111 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004112{
4113 struct audio_device *adev = (struct audio_device *)dev;
4114 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004115 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004116 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004117 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004118 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004119 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4120 devices,
4121 flags,
4122 source);
4123 ALOGE("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004125
4126 if (config->sample_rate == 0)
4127 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4128 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4129 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4130 if (config->format == AUDIO_FORMAT_DEFAULT)
4131 config->format = AUDIO_FORMAT_PCM_16_BIT;
4132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004133 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
4134 return -EINVAL;
4135
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004136 if (audio_extn_tfa_98xx_is_supported() &&
4137 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004138 return -EINVAL;
4139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4141
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004142 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004143 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145 in->stream.common.get_sample_rate = in_get_sample_rate;
4146 in->stream.common.set_sample_rate = in_set_sample_rate;
4147 in->stream.common.get_buffer_size = in_get_buffer_size;
4148 in->stream.common.get_channels = in_get_channels;
4149 in->stream.common.get_format = in_get_format;
4150 in->stream.common.set_format = in_set_format;
4151 in->stream.common.standby = in_standby;
4152 in->stream.common.dump = in_dump;
4153 in->stream.common.set_parameters = in_set_parameters;
4154 in->stream.common.get_parameters = in_get_parameters;
4155 in->stream.common.add_audio_effect = in_add_audio_effect;
4156 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4157 in->stream.set_gain = in_set_gain;
4158 in->stream.read = in_read;
4159 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004160 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161
4162 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004163 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004165 in->standby = 1;
4166 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004167 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004168 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004169
Haynes Mathew George569b7482017-05-08 14:44:27 -07004170 if (is_usb_dev && may_use_hifi_record) {
4171 /* HiFi record selects an appropriate format, channel, rate combo
4172 depending on sink capabilities*/
4173 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4174 &config->format,
4175 &in->supported_formats[0],
4176 MAX_SUPPORTED_FORMATS,
4177 &config->channel_mask,
4178 &in->supported_channel_masks[0],
4179 MAX_SUPPORTED_CHANNEL_MASKS,
4180 &config->sample_rate,
4181 &in->supported_sample_rates[0],
4182 MAX_SUPPORTED_SAMPLE_RATES);
4183 if (ret != 0) {
4184 ret = -EINVAL;
4185 goto err_open;
4186 }
4187 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004188 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004189 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4190 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4191 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4192 bool ret_error = false;
4193 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4194 from HAL is 8_24
4195 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4196 8_24 return error indicating supported format is 8_24
4197 *> In case of any other source requesting 24 bit or float return error
4198 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004199
vivek mehta57ff9b52016-04-28 14:13:08 -07004200 on error flinger will retry with supported format passed
4201 */
4202 if (source != AUDIO_SOURCE_UNPROCESSED) {
4203 config->format = AUDIO_FORMAT_PCM_16_BIT;
4204 ret_error = true;
4205 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4206 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4207 ret_error = true;
4208 }
4209
4210 if (ret_error) {
4211 ret = -EINVAL;
4212 goto err_open;
4213 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004214 }
4215
vivek mehta57ff9b52016-04-28 14:13:08 -07004216 in->format = config->format;
4217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004218 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004219 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4220 if (config->sample_rate == 0)
4221 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4222 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4223 config->sample_rate != 8000) {
4224 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4225 ret = -EINVAL;
4226 goto err_open;
4227 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004228
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004229 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4230 config->format = AUDIO_FORMAT_PCM_16_BIT;
4231 ret = -EINVAL;
4232 goto err_open;
4233 }
4234
4235 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4236 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004237 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004238 } else if (is_usb_dev && may_use_hifi_record) {
4239 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4240 in->config = pcm_config_audio_capture;
4241 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004242 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4243 config->sample_rate,
4244 config->format,
4245 channel_count,
4246 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004247 in->config.period_size = buffer_size / frame_size;
4248 in->config.rate = config->sample_rate;
4249 in->af_period_multiplier = 1;
4250 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004251 } else {
4252 in->usecase = USECASE_AUDIO_RECORD;
4253 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004254 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004255 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004256#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004257 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004258#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004259 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004260 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004261 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004262 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004263 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4264 config->sample_rate,
4265 config->format,
4266 channel_count,
4267 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004268 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004269 in->config.rate = config->sample_rate;
4270 in->af_period_multiplier = 1;
4271 } else {
4272 // period size is left untouched for rt mode playback
4273 in->config = pcm_config_audio_capture_rt;
4274 in->af_period_multiplier = af_period_multiplier;
4275 }
4276 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4277 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004278 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004279 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4280 in->config = pcm_config_mmap_capture;
4281 in->stream.start = in_start;
4282 in->stream.stop = in_stop;
4283 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4284 in->stream.get_mmap_position = in_get_mmap_position;
4285 in->af_period_multiplier = 1;
4286 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004287 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
4288 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004289 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004290 (config->sample_rate == 8000 ||
4291 config->sample_rate == 16000 ||
4292 config->sample_rate == 32000 ||
4293 config->sample_rate == 48000) &&
4294 channel_count == 1) {
4295 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4296 in->config = pcm_config_audio_capture;
4297 frame_size = audio_stream_in_frame_size(&in->stream);
4298 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4299 config->sample_rate,
4300 config->format,
4301 channel_count, false /*is_low_latency*/);
4302 in->config.period_size = buffer_size / frame_size;
4303 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4304 in->config.rate = config->sample_rate;
4305 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004306 } else {
4307 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004308 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004309 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4310 config->sample_rate,
4311 config->format,
4312 channel_count,
4313 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004314 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004315 in->config.rate = config->sample_rate;
4316 in->af_period_multiplier = 1;
4317 }
4318 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4319 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004320 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004322 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004323 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004324
Andy Hungd13f0d32017-06-12 13:58:37 -07004325 in->error_log = error_log_create(
4326 ERROR_LOG_ENTRIES,
4327 NANOS_PER_SECOND /* aggregate consecutive identical errors within one second */);
4328
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004329 /* This stream could be for sound trigger lab,
4330 get sound trigger pcm if present */
4331 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004332
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004333 lock_input_stream(in);
4334 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4335 pthread_mutex_lock(&adev->lock);
4336 in->card_status = adev->card_status;
4337 pthread_mutex_unlock(&adev->lock);
4338 pthread_mutex_unlock(&in->lock);
4339
vivek mehta4a824772017-06-08 19:05:49 -07004340 stream_app_type_cfg_init(&in->app_type_cfg);
4341
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004342 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004343 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004344 return 0;
4345
4346err_open:
4347 free(in);
4348 *stream_in = NULL;
4349 return ret;
4350}
4351
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004352static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353 struct audio_stream_in *stream)
4354{
Andy Hungd13f0d32017-06-12 13:58:37 -07004355 struct stream_in *in = (struct stream_in *)stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004356 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004357
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004358 // must deregister from sndmonitor first to prevent races
4359 // between the callback and close_stream
4360 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004361 in_standby(&stream->common);
Andy Hungd13f0d32017-06-12 13:58:37 -07004362
4363 error_log_destroy(in->error_log);
4364 in->error_log = NULL;
4365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004366 free(stream);
4367
4368 return;
4369}
4370
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004371static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372{
4373 return 0;
4374}
4375
Andy Hung31aca912014-03-20 17:14:59 -07004376/* verifies input and output devices and their capabilities.
4377 *
4378 * This verification is required when enabling extended bit-depth or
4379 * sampling rates, as not all qcom products support it.
4380 *
4381 * Suitable for calling only on initialization such as adev_open().
4382 * It fills the audio_device use_case_table[] array.
4383 *
4384 * Has a side-effect that it needs to configure audio routing / devices
4385 * in order to power up the devices and read the device parameters.
4386 * It does not acquire any hw device lock. Should restore the devices
4387 * back to "normal state" upon completion.
4388 */
4389static int adev_verify_devices(struct audio_device *adev)
4390{
4391 /* enumeration is a bit difficult because one really wants to pull
4392 * the use_case, device id, etc from the hidden pcm_device_table[].
4393 * In this case there are the following use cases and device ids.
4394 *
4395 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4396 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004397 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004398 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4399 * [USECASE_AUDIO_RECORD] = {0, 0},
4400 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4401 * [USECASE_VOICE_CALL] = {2, 2},
4402 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004403 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004404 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4405 */
4406
4407 /* should be the usecases enabled in adev_open_input_stream() */
4408 static const int test_in_usecases[] = {
4409 USECASE_AUDIO_RECORD,
4410 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4411 };
4412 /* should be the usecases enabled in adev_open_output_stream()*/
4413 static const int test_out_usecases[] = {
4414 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4415 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4416 };
4417 static const usecase_type_t usecase_type_by_dir[] = {
4418 PCM_PLAYBACK,
4419 PCM_CAPTURE,
4420 };
4421 static const unsigned flags_by_dir[] = {
4422 PCM_OUT,
4423 PCM_IN,
4424 };
4425
4426 size_t i;
4427 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004428 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004429 char info[512]; /* for possible debug info */
4430
4431 for (dir = 0; dir < 2; ++dir) {
4432 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4433 const unsigned flags_dir = flags_by_dir[dir];
4434 const size_t testsize =
4435 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4436 const int *testcases =
4437 dir ? test_in_usecases : test_out_usecases;
4438 const audio_devices_t audio_device =
4439 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4440
4441 for (i = 0; i < testsize; ++i) {
4442 const audio_usecase_t audio_usecase = testcases[i];
4443 int device_id;
4444 snd_device_t snd_device;
4445 struct pcm_params **pparams;
4446 struct stream_out out;
4447 struct stream_in in;
4448 struct audio_usecase uc_info;
4449 int retval;
4450
4451 pparams = &adev->use_case_table[audio_usecase];
4452 pcm_params_free(*pparams); /* can accept null input */
4453 *pparams = NULL;
4454
4455 /* find the device ID for the use case (signed, for error) */
4456 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4457 if (device_id < 0)
4458 continue;
4459
4460 /* prepare structures for device probing */
4461 memset(&uc_info, 0, sizeof(uc_info));
4462 uc_info.id = audio_usecase;
4463 uc_info.type = usecase_type;
4464 if (dir) {
4465 adev->active_input = &in;
4466 memset(&in, 0, sizeof(in));
4467 in.device = audio_device;
4468 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4469 uc_info.stream.in = &in;
4470 } else {
4471 adev->active_input = NULL;
4472 }
4473 memset(&out, 0, sizeof(out));
4474 out.devices = audio_device; /* only field needed in select_devices */
4475 uc_info.stream.out = &out;
4476 uc_info.devices = audio_device;
4477 uc_info.in_snd_device = SND_DEVICE_NONE;
4478 uc_info.out_snd_device = SND_DEVICE_NONE;
4479 list_add_tail(&adev->usecase_list, &uc_info.list);
4480
4481 /* select device - similar to start_(in/out)put_stream() */
4482 retval = select_devices(adev, audio_usecase);
4483 if (retval >= 0) {
4484 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4485#if LOG_NDEBUG == 0
4486 if (*pparams) {
4487 ALOGV("%s: (%s) card %d device %d", __func__,
4488 dir ? "input" : "output", card_id, device_id);
4489 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004490 } else {
4491 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4492 }
4493#endif
4494 }
4495
4496 /* deselect device - similar to stop_(in/out)put_stream() */
4497 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004498 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004499 /* 2. Disable the rx device */
4500 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004501 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004502 list_remove(&uc_info.list);
4503 }
4504 }
4505 adev->active_input = NULL; /* restore adev state */
4506 return 0;
4507}
4508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509static int adev_close(hw_device_t *device)
4510{
Andy Hung31aca912014-03-20 17:14:59 -07004511 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004513
4514 if (!adev)
4515 return 0;
4516
4517 pthread_mutex_lock(&adev_init_lock);
4518
4519 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004520 audio_extn_snd_mon_unregister_listener(adev);
4521 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004522 audio_route_free(adev->audio_route);
4523 free(adev->snd_dev_ref_cnt);
4524 platform_deinit(adev->platform);
4525 audio_extn_extspk_deinit(adev->extspk);
4526 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004527 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004528 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4529 pcm_params_free(adev->use_case_table[i]);
4530 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004531 if (adev->adm_deinit)
4532 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004533 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004534 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004535
4536 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004537
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004538 return 0;
4539}
4540
Glenn Kasten4f993392014-05-14 07:30:48 -07004541/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4542 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4543 * just that it _might_ work.
4544 */
4545static int period_size_is_plausible_for_low_latency(int period_size)
4546{
4547 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004548 case 48:
4549 case 96:
4550 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004551 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004552 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004553 case 240:
4554 case 320:
4555 case 480:
4556 return 1;
4557 default:
4558 return 0;
4559 }
4560}
4561
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004562static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4563{
4564 int card;
4565 card_status_t status;
4566
4567 if (!parms)
4568 return;
4569
4570 if (parse_snd_card_status(parms, &card, &status) < 0)
4571 return;
4572
4573 pthread_mutex_lock(&adev->lock);
4574 bool valid_cb = (card == adev->snd_card);
4575 if (valid_cb) {
4576 if (adev->card_status != status) {
4577 adev->card_status = status;
4578 platform_snd_card_update(adev->platform, status);
4579 }
4580 }
4581 pthread_mutex_unlock(&adev->lock);
4582 return;
4583}
4584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004585static int adev_open(const hw_module_t *module, const char *name,
4586 hw_device_t **device)
4587{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004588 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004589
Eric Laurent2bafff12016-03-17 12:17:23 -07004590 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004591 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004592 pthread_mutex_lock(&adev_init_lock);
4593 if (audio_device_ref_count != 0) {
4594 *device = &adev->device.common;
4595 audio_device_ref_count++;
4596 ALOGV("%s: returning existing instance of adev", __func__);
4597 ALOGV("%s: exit", __func__);
4598 pthread_mutex_unlock(&adev_init_lock);
4599 return 0;
4600 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004601 adev = calloc(1, sizeof(struct audio_device));
4602
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004603 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4604
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4606 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4607 adev->device.common.module = (struct hw_module_t *)module;
4608 adev->device.common.close = adev_close;
4609
4610 adev->device.init_check = adev_init_check;
4611 adev->device.set_voice_volume = adev_set_voice_volume;
4612 adev->device.set_master_volume = adev_set_master_volume;
4613 adev->device.get_master_volume = adev_get_master_volume;
4614 adev->device.set_master_mute = adev_set_master_mute;
4615 adev->device.get_master_mute = adev_get_master_mute;
4616 adev->device.set_mode = adev_set_mode;
4617 adev->device.set_mic_mute = adev_set_mic_mute;
4618 adev->device.get_mic_mute = adev_get_mic_mute;
4619 adev->device.set_parameters = adev_set_parameters;
4620 adev->device.get_parameters = adev_get_parameters;
4621 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4622 adev->device.open_output_stream = adev_open_output_stream;
4623 adev->device.close_output_stream = adev_close_output_stream;
4624 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004626 adev->device.close_input_stream = adev_close_input_stream;
4627 adev->device.dump = adev_dump;
4628
4629 /* Set the default route before the PCM stream is opened */
4630 pthread_mutex_lock(&adev->lock);
4631 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004632 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004633 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004634 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004635 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004636 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004637 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004638 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004639 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640 pthread_mutex_unlock(&adev->lock);
4641
4642 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004643 adev->platform = platform_init(adev);
4644 if (!adev->platform) {
4645 free(adev->snd_dev_ref_cnt);
4646 free(adev);
4647 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4648 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004649 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004650 return -EINVAL;
4651 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004652 adev->extspk = audio_extn_extspk_init(adev);
4653
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004654 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4655 if (adev->visualizer_lib == NULL) {
4656 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4657 } else {
4658 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4659 adev->visualizer_start_output =
4660 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4661 "visualizer_hal_start_output");
4662 adev->visualizer_stop_output =
4663 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4664 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004665 }
4666
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004667 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4668 if (adev->offload_effects_lib == NULL) {
4669 ALOGW("%s: DLOPEN failed for %s", __func__,
4670 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4671 } else {
4672 ALOGV("%s: DLOPEN successful for %s", __func__,
4673 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4674 adev->offload_effects_start_output =
4675 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4676 "offload_effects_bundle_hal_start_output");
4677 adev->offload_effects_stop_output =
4678 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4679 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004680 }
4681
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004682 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4683 if (adev->adm_lib == NULL) {
4684 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4685 } else {
4686 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4687 adev->adm_init = (adm_init_t)
4688 dlsym(adev->adm_lib, "adm_init");
4689 adev->adm_deinit = (adm_deinit_t)
4690 dlsym(adev->adm_lib, "adm_deinit");
4691 adev->adm_register_input_stream = (adm_register_input_stream_t)
4692 dlsym(adev->adm_lib, "adm_register_input_stream");
4693 adev->adm_register_output_stream = (adm_register_output_stream_t)
4694 dlsym(adev->adm_lib, "adm_register_output_stream");
4695 adev->adm_deregister_stream = (adm_deregister_stream_t)
4696 dlsym(adev->adm_lib, "adm_deregister_stream");
4697 adev->adm_request_focus = (adm_request_focus_t)
4698 dlsym(adev->adm_lib, "adm_request_focus");
4699 adev->adm_abandon_focus = (adm_abandon_focus_t)
4700 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004701 adev->adm_set_config = (adm_set_config_t)
4702 dlsym(adev->adm_lib, "adm_set_config");
4703 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4704 dlsym(adev->adm_lib, "adm_request_focus_v2");
4705 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4706 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4707 adev->adm_on_routing_change = (adm_on_routing_change_t)
4708 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004709 }
4710
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004711 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004712 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004715
Andy Hung31aca912014-03-20 17:14:59 -07004716 if (k_enable_extended_precision)
4717 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004718
Glenn Kasten4f993392014-05-14 07:30:48 -07004719 char value[PROPERTY_VALUE_MAX];
4720 int trial;
4721 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4722 trial = atoi(value);
4723 if (period_size_is_plausible_for_low_latency(trial)) {
4724 pcm_config_low_latency.period_size = trial;
4725 pcm_config_low_latency.start_threshold = trial / 4;
4726 pcm_config_low_latency.avail_min = trial / 4;
4727 configured_low_latency_capture_period_size = trial;
4728 }
4729 }
4730 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4731 trial = atoi(value);
4732 if (period_size_is_plausible_for_low_latency(trial)) {
4733 configured_low_latency_capture_period_size = trial;
4734 }
4735 }
4736
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004737 // commented as full set of app type cfg is sent from platform
4738 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004739 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004740
4741 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4742 af_period_multiplier = atoi(value);
4743 if (af_period_multiplier < 0) {
4744 af_period_multiplier = 2;
4745 } else if (af_period_multiplier > 4) {
4746 af_period_multiplier = 4;
4747 }
4748 ALOGV("new period_multiplier = %d", af_period_multiplier);
4749 }
4750
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004751 audio_extn_tfa_98xx_init(adev);
4752
vivek mehta1a9b7c02015-06-25 11:49:38 -07004753 pthread_mutex_unlock(&adev_init_lock);
4754
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004755 if (adev->adm_init)
4756 adev->adm_data = adev->adm_init();
4757
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004758 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004759 audio_extn_snd_mon_init();
4760 pthread_mutex_lock(&adev->lock);
4761 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4762 adev->card_status = CARD_STATUS_ONLINE;
4763 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004764 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004765
Eric Laurent2bafff12016-03-17 12:17:23 -07004766 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004767 return 0;
4768}
4769
4770static struct hw_module_methods_t hal_module_methods = {
4771 .open = adev_open,
4772};
4773
4774struct audio_module HAL_MODULE_INFO_SYM = {
4775 .common = {
4776 .tag = HARDWARE_MODULE_TAG,
4777 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4778 .hal_api_version = HARDWARE_HAL_API_VERSION,
4779 .id = AUDIO_HARDWARE_MODULE_ID,
4780 .name = "QCOM Audio HAL",
4781 .author = "Code Aurora Forum",
4782 .methods = &hal_module_methods,
4783 },
4784};