blob: b885841808fabb82b2fb97d89716a09f896e4daf [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>
52#include <audio_utils/power.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080054#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070055#include "platform_api.h"
56#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070057#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070059#include "sound/compress_params.h"
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -080060#include "audio_extn/tfa_98xx.h"
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061
Eric Laurent397db572016-05-11 11:31:47 -070062/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
63 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070064#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070065// 2 buffers causes problems with high bitrate files
66#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070067/* ToDo: Check and update a proper value in msec */
68#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
vivek mehta4a824772017-06-08 19:05:49 -070069/* treat as unsigned Q1.13 */
70#define APP_TYPE_GAIN_DEFAULT 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070071#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
vivek mehta4a824772017-06-08 19:05:49 -070072
73/* treat as unsigned Q1.13 */
vivek mehtaa68fea62017-06-08 19:04:02 -070074#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070075
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070076#define PROXY_OPEN_RETRY_COUNT 100
77#define PROXY_OPEN_WAIT_TIME 20
78
vivek mehtadae44712015-07-27 14:13:18 -070079#define MIN_CHANNEL_COUNT 1
80#define DEFAULT_CHANNEL_COUNT 2
81
Jean-Michel Trivic0750692015-10-12 12:12:32 -070082#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
83#define MAX_CHANNEL_COUNT 1
84#else
vivek mehtadae44712015-07-27 14:13:18 -070085#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
86#define XSTR(x) STR(x)
87#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070088#endif
vivek mehtadae44712015-07-27 14:13:18 -070089
Haynes Mathew George03c40102016-01-29 17:57:48 -080090#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
91
Glenn Kasten4f993392014-05-14 07:30:48 -070092static unsigned int configured_low_latency_capture_period_size =
93 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
94
Eric Laurent0e46adf2016-12-16 12:49:24 -080095
96#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Phil Burkbc991042017-02-24 08:06:44 -080097#define MMAP_PERIOD_COUNT_MIN 32
98#define MMAP_PERIOD_COUNT_MAX 512
99#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
Eric Laurent0e46adf2016-12-16 12:49:24 -0800100
101
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
Andy Hung9e737de2017-05-22 10:51:22 -0700313// TODO: Consider moving this to a pthread_once() if we have more
314// static initialization required.
315static bool is_userdebug_or_eng_build() {
316 char value[PROPERTY_VALUE_MAX];
317 (void)property_get("ro.build.type", value, "unknown"); // ignore actual length
318 return strcmp(value, "userdebug") == 0 || strcmp(value, "eng") == 0;
319}
320
Haynes Mathew George03c40102016-01-29 17:57:48 -0800321static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
322 int flags __unused)
323{
324 int dir = 0;
325 switch (uc_id) {
326 case USECASE_AUDIO_RECORD_LOW_LATENCY:
327 dir = 1;
328 case USECASE_AUDIO_PLAYBACK_ULL:
329 break;
330 default:
331 return false;
332 }
333
334 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
335 PCM_PLAYBACK : PCM_CAPTURE);
336 if (adev->adm_is_noirq_avail)
337 return adev->adm_is_noirq_avail(adev->adm_data,
338 adev->snd_card, dev_id, dir);
339 return false;
340}
341
342static void register_out_stream(struct stream_out *out)
343{
344 struct audio_device *adev = out->dev;
345 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
346 return;
347
348 if (!adev->adm_register_output_stream)
349 return;
350
351 adev->adm_register_output_stream(adev->adm_data,
352 out->handle,
353 out->flags);
354
355 if (!adev->adm_set_config)
356 return;
357
358 if (out->realtime) {
359 adev->adm_set_config(adev->adm_data,
360 out->handle,
361 out->pcm, &out->config);
362 }
363}
364
365static void register_in_stream(struct stream_in *in)
366{
367 struct audio_device *adev = in->dev;
368 if (!adev->adm_register_input_stream)
369 return;
370
371 adev->adm_register_input_stream(adev->adm_data,
372 in->capture_handle,
373 in->flags);
374
375 if (!adev->adm_set_config)
376 return;
377
378 if (in->realtime) {
379 adev->adm_set_config(adev->adm_data,
380 in->capture_handle,
381 in->pcm,
382 &in->config);
383 }
384}
385
386static void request_out_focus(struct stream_out *out, long ns)
387{
388 struct audio_device *adev = out->dev;
389
Haynes Mathew George03c40102016-01-29 17:57:48 -0800390 if (adev->adm_request_focus_v2) {
391 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
392 } else if (adev->adm_request_focus) {
393 adev->adm_request_focus(adev->adm_data, out->handle);
394 }
395}
396
397static void request_in_focus(struct stream_in *in, long ns)
398{
399 struct audio_device *adev = in->dev;
400
Haynes Mathew George03c40102016-01-29 17:57:48 -0800401 if (adev->adm_request_focus_v2) {
402 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
403 } else if (adev->adm_request_focus) {
404 adev->adm_request_focus(adev->adm_data, in->capture_handle);
405 }
406}
407
408static void release_out_focus(struct stream_out *out, long ns __unused)
409{
410 struct audio_device *adev = out->dev;
411
412 if (adev->adm_abandon_focus)
413 adev->adm_abandon_focus(adev->adm_data, out->handle);
414}
415
416static void release_in_focus(struct stream_in *in, long ns __unused)
417{
418 struct audio_device *adev = in->dev;
419 if (adev->adm_abandon_focus)
420 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
421}
422
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -0700423static int parse_snd_card_status(struct str_parms * parms, int * card,
424 card_status_t * status)
425{
426 char value[32]={0};
427 char state[32]={0};
428
429 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
430
431 if (ret < 0)
432 return -1;
433
434 // sscanf should be okay as value is of max length 32.
435 // same as sizeof state.
436 if (sscanf(value, "%d,%s", card, state) < 2)
437 return -1;
438
439 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
440 CARD_STATUS_OFFLINE;
441 return 0;
442}
443
vivek mehta1a9b7c02015-06-25 11:49:38 -0700444__attribute__ ((visibility ("default")))
445bool audio_hw_send_gain_dep_calibration(int level) {
446 bool ret_val = false;
447 ALOGV("%s: enter ... ", __func__);
448
449 pthread_mutex_lock(&adev_init_lock);
450
451 if (adev != NULL && adev->platform != NULL) {
452 pthread_mutex_lock(&adev->lock);
453 ret_val = platform_send_gain_dep_cal(adev->platform, level);
454 pthread_mutex_unlock(&adev->lock);
vivek mehtafb4d7bd2016-04-29 03:16:47 -0700455
456 // if cal set fails, cache level info
457 // if cal set succeds, reset known last cal set
458 if (!ret_val)
459 last_known_cal_step = level;
460 else if (last_known_cal_step != -1)
461 last_known_cal_step = -1;
vivek mehta1a9b7c02015-06-25 11:49:38 -0700462 } else {
463 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
464 }
465
466 pthread_mutex_unlock(&adev_init_lock);
467
468 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
469 return ret_val;
470}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700471
vivek mehtaa8d7c922016-05-25 14:40:44 -0700472__attribute__ ((visibility ("default")))
473int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
474 int table_size) {
475 int ret_val = 0;
476 ALOGV("%s: enter ... ", __func__);
477
478 pthread_mutex_lock(&adev_init_lock);
479 if (adev == NULL) {
480 ALOGW("%s: adev is NULL .... ", __func__);
481 goto done;
482 }
483
484 pthread_mutex_lock(&adev->lock);
485 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
486 pthread_mutex_unlock(&adev->lock);
487done:
488 pthread_mutex_unlock(&adev_init_lock);
489 ALOGV("%s: exit ... ", __func__);
490 return ret_val;
491}
492
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700493static bool is_supported_format(audio_format_t format)
494{
Eric Laurent8251ac82014-07-23 11:00:25 -0700495 switch (format) {
496 case AUDIO_FORMAT_MP3:
497 case AUDIO_FORMAT_AAC_LC:
498 case AUDIO_FORMAT_AAC_HE_V1:
499 case AUDIO_FORMAT_AAC_HE_V2:
500 return true;
501 default:
502 break;
503 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700504 return false;
505}
506
Haynes Mathew George03c40102016-01-29 17:57:48 -0800507static inline bool is_mmap_usecase(audio_usecase_t uc_id)
508{
509 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
510 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
511}
512
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700513static int get_snd_codec_id(audio_format_t format)
514{
515 int id = 0;
516
Eric Laurent8251ac82014-07-23 11:00:25 -0700517 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700518 case AUDIO_FORMAT_MP3:
519 id = SND_AUDIOCODEC_MP3;
520 break;
521 case AUDIO_FORMAT_AAC:
522 id = SND_AUDIOCODEC_AAC;
523 break;
524 default:
525 ALOGE("%s: Unsupported audio format", __func__);
526 }
527
528 return id;
529}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800530
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800531static int audio_ssr_status(struct audio_device *adev)
532{
533 int ret = 0;
534 struct mixer_ctl *ctl;
535 const char *mixer_ctl_name = "Audio SSR Status";
536
537 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
538 ret = mixer_ctl_get_value(ctl, 0);
539 ALOGD("%s: value: %d", __func__, ret);
540 return ret;
541}
542
vivek mehta4a824772017-06-08 19:05:49 -0700543static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
544{
545 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
546}
547
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800548int enable_audio_route(struct audio_device *adev,
549 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700551 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800552 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800553
554 if (usecase == NULL)
555 return -EINVAL;
556
557 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
558
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800559 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700560 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800561 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800563
Yamit Mehtae3b99562016-09-16 22:44:00 +0530564 audio_extn_utils_send_app_type_cfg(adev, usecase);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800565 audio_extn_utils_send_audio_calibration(adev, usecase);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800566 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500567 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700568 ALOGD("%s: usecase(%d) apply and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700569 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800570
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800571 ALOGV("%s: exit", __func__);
572 return 0;
573}
574
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800575int disable_audio_route(struct audio_device *adev,
576 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800577{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700578 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800579 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800580
581 if (usecase == NULL)
582 return -EINVAL;
583
584 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700585 if (usecase->type == PCM_CAPTURE)
586 snd_device = usecase->in_snd_device;
587 else
588 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800589 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500590 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Eric Laurent2e140aa2016-06-30 17:14:46 -0700591 ALOGD("%s: usecase(%d) reset and update mixer path: %s", __func__, usecase->id, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700592 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800593
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800594 ALOGV("%s: exit", __func__);
595 return 0;
596}
597
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800598int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700599 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800600{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700601 int i, num_devices = 0;
602 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800603 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800604 if (snd_device < SND_DEVICE_MIN ||
605 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800606 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800607 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800608 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700609
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700610 platform_send_audio_calibration(adev->platform, snd_device);
611
vivek mehtade4849c2016-03-03 17:23:38 -0800612 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700613 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700614 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800615 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 }
617
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700618 /* due to the possibility of calibration overwrite between listen
619 and audio, notify sound trigger hal before audio calibration is sent */
620 audio_extn_sound_trigger_update_device_status(snd_device,
621 ST_EVENT_SND_DEVICE_BUSY);
622
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700623 if (audio_extn_spkr_prot_is_enabled())
624 audio_extn_spkr_prot_calib_cancel(adev);
625
zhaoyang yin4211fad2015-06-04 21:13:25 +0800626 audio_extn_dsm_feedback_enable(adev, snd_device, true);
627
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700628 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
629 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
630 audio_extn_spkr_prot_is_enabled()) {
631 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800632 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700633 }
634 if (audio_extn_spkr_prot_start_processing(snd_device)) {
635 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800636 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700637 }
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700638 } else if (platform_can_split_snd_device(snd_device,
639 &num_devices,
640 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700641 for (i = 0; i < num_devices; i++) {
642 enable_snd_device(adev, new_snd_devices[i]);
643 }
vivek mehtab6506412015-08-07 16:55:17 -0700644 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700645 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800646 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
647 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
648 ALOGE(" %s: Invalid sound device returned", __func__);
649 goto on_error;
650 }
Ed Tam70b5c142016-03-21 19:14:29 -0700651
Eric Laurent2e140aa2016-06-30 17:14:46 -0700652 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800653 audio_route_apply_and_update_path(adev->audio_route, device_name);
654 }
655on_success:
656 adev->snd_dev_ref_cnt[snd_device]++;
657 ret_val = 0;
658on_error:
659 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800660}
661
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800662int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700663 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800664{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700665 int i, num_devices = 0;
666 snd_device_t new_snd_devices[2];
667
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800668 if (snd_device < SND_DEVICE_MIN ||
669 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800670 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800671 return -EINVAL;
672 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700673 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
674 ALOGE("%s: device ref cnt is already 0", __func__);
675 return -EINVAL;
676 }
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -0800677 audio_extn_tfa_98xx_disable_speaker(snd_device);
678
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700679 adev->snd_dev_ref_cnt[snd_device]--;
680 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800681 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700682 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
vivek mehtae59cfb22017-06-16 15:57:11 -0700683 snd_device == SND_DEVICE_OUT_SPEAKER_REVERSE ||
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700684 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
685 audio_extn_spkr_prot_is_enabled()) {
686 audio_extn_spkr_prot_stop_processing(snd_device);
vivek mehtae59cfb22017-06-16 15:57:11 -0700687
688 // when speaker device is disabled, reset swap.
689 // will be renabled on usecase start
690 platform_set_swap_channels(adev, false);
691
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700692 } else if (platform_can_split_snd_device(snd_device,
693 &num_devices,
694 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700695 for (i = 0; i < num_devices; i++) {
696 disable_snd_device(adev, new_snd_devices[i]);
697 }
vivek mehtab6506412015-08-07 16:55:17 -0700698 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700699 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800700 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
701 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
702 ALOGE(" %s: Invalid sound device returned", __func__);
703 return -EINVAL;
704 }
705
Eric Laurent2e140aa2016-06-30 17:14:46 -0700706 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800707 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700708 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700709 audio_extn_sound_trigger_update_device_status(snd_device,
710 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 }
vivek mehtab6506412015-08-07 16:55:17 -0700712
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800713 return 0;
714}
715
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700716/*
717 legend:
718 uc - existing usecase
719 new_uc - new usecase
720 d1, d11, d2 - SND_DEVICE enums
721 a1, a2 - corresponding ANDROID device enums
722 B, B1, B2 - backend strings
723
724case 1
725 uc->dev d1 (a1) B1
726 new_uc->dev d1 (a1), d2 (a2) B1, B2
727
728 resolution: disable and enable uc->dev on d1
729
730case 2
731 uc->dev d1 (a1) B1
732 new_uc->dev d11 (a1) B1
733
734 resolution: need to switch uc since d1 and d11 are related
735 (e.g. speaker and voice-speaker)
736 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
737
738case 3
739 uc->dev d1 (a1) B1
740 new_uc->dev d2 (a2) B2
741
742 resolution: no need to switch uc
743
744case 4
745 uc->dev d1 (a1) B
746 new_uc->dev d2 (a2) B
747
748 resolution: disable enable uc-dev on d2 since backends match
749 we cannot enable two streams on two different devices if they
750 share the same backend. e.g. if offload is on speaker device using
751 QUAD_MI2S backend and a low-latency stream is started on voice-handset
752 using the same backend, offload must also be switched to voice-handset.
753
754case 5
755 uc->dev d1 (a1) B
756 new_uc->dev d1 (a1), d2 (a2) B
757
758 resolution: disable enable uc-dev on d2 since backends match
759 we cannot enable two streams on two different devices if they
760 share the same backend.
761
762case 6
763 uc->dev d1 a1 B1
764 new_uc->dev d2 a1 B2
765
766 resolution: no need to switch
767
768case 7
769
770 uc->dev d1 (a1), d2 (a2) B1, B2
771 new_uc->dev d1 B1
772
773 resolution: no need to switch
774
775*/
776static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
777 struct audio_usecase *new_uc,
778 snd_device_t new_snd_device)
779{
780 audio_devices_t a1 = uc->stream.out->devices;
781 audio_devices_t a2 = new_uc->stream.out->devices;
782
783 snd_device_t d1 = uc->out_snd_device;
784 snd_device_t d2 = new_snd_device;
785
786 // Treat as a special case when a1 and a2 are not disjoint
787 if ((a1 != a2) && (a1 & a2)) {
788 snd_device_t d3[2];
789 int num_devices = 0;
790 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
791 &num_devices,
792 d3);
793 if (ret < 0) {
794 if (ret != -ENOSYS) {
795 ALOGW("%s failed to split snd_device %d",
796 __func__,
797 popcount(a1) > 1 ? d1 : d2);
798 }
799 goto end;
800 }
801
802 // NB: case 7 is hypothetical and isn't a practical usecase yet.
803 // But if it does happen, we need to give priority to d2 if
804 // the combo devices active on the existing usecase share a backend.
805 // This is because we cannot have a usecase active on a combo device
806 // and a new usecase requests one device in this combo pair.
807 if (platform_check_backends_match(d3[0], d3[1])) {
808 return d2; // case 5
809 } else {
810 return d1; // case 1
811 }
812 } else {
813 if (platform_check_backends_match(d1, d2)) {
814 return d2; // case 2, 4
815 } else {
816 return d1; // case 6, 3
817 }
818 }
819
820end:
821 return d2; // return whatever was calculated before.
822}
823
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700824static void check_and_route_playback_usecases(struct audio_device *adev,
825 struct audio_usecase *uc_info,
826 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700827{
828 struct listnode *node;
829 struct audio_usecase *usecase;
830 bool switch_device[AUDIO_USECASE_MAX];
831 int i, num_uc_to_switch = 0;
832
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700833 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
834 uc_info,
835 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700836
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837 /*
838 * This function is to make sure that all the usecases that are active on
839 * the hardware codec backend are always routed to any one device that is
840 * handled by the hardware codec.
841 * For example, if low-latency and deep-buffer usecases are currently active
842 * on speaker and out_set_parameters(headset) is received on low-latency
843 * output, then we have to make sure deep-buffer is also switched to headset,
844 * because of the limitation that both the devices cannot be enabled
845 * at the same time as they share the same backend.
846 */
847 /* Disable all the usecases on the shared backend other than the
848 specified usecase */
849 for (i = 0; i < AUDIO_USECASE_MAX; i++)
850 switch_device[i] = false;
851
852 list_for_each(node, &adev->usecase_list) {
853 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700854 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
855 continue;
856
857 if (force_routing ||
858 (usecase->out_snd_device != snd_device &&
859 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
860 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700861 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
862 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700863 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700864 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 switch_device[usecase->id] = true;
866 num_uc_to_switch++;
867 }
868 }
869
870 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 list_for_each(node, &adev->usecase_list) {
872 usecase = node_to_item(node, struct audio_usecase, list);
873 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700874 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900875 }
876 }
877
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700878 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900879 list_for_each(node, &adev->usecase_list) {
880 usecase = node_to_item(node, struct audio_usecase, list);
881 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700882 d_device = derive_playback_snd_device(usecase, uc_info,
883 snd_device);
884 enable_snd_device(adev, d_device);
885 /* Update the out_snd_device before enabling the audio route */
886 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 }
888 }
889
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 /* Re-route all the usecases on the shared backend other than the
891 specified usecase to new snd devices */
892 list_for_each(node, &adev->usecase_list) {
893 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700894 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700895 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700896 }
897 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 }
899}
900
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700901static void check_and_route_capture_usecases(struct audio_device *adev,
902 struct audio_usecase *uc_info,
903 snd_device_t snd_device)
904{
905 struct listnode *node;
906 struct audio_usecase *usecase;
907 bool switch_device[AUDIO_USECASE_MAX];
908 int i, num_uc_to_switch = 0;
909
vivek mehta4ed66e62016-04-15 23:33:34 -0700910 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
911
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700912 /*
913 * This function is to make sure that all the active capture usecases
914 * are always routed to the same input sound device.
915 * For example, if audio-record and voice-call usecases are currently
916 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
917 * is received for voice call then we have to make sure that audio-record
918 * usecase is also switched to earpiece i.e. voice-dmic-ef,
919 * because of the limitation that two devices cannot be enabled
920 * at the same time if they share the same backend.
921 */
922 for (i = 0; i < AUDIO_USECASE_MAX; i++)
923 switch_device[i] = false;
924
925 list_for_each(node, &adev->usecase_list) {
926 usecase = node_to_item(node, struct audio_usecase, list);
927 if (usecase->type != PCM_PLAYBACK &&
928 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700929 usecase->in_snd_device != snd_device &&
930 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700931 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
932 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700933 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700934 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700935 switch_device[usecase->id] = true;
936 num_uc_to_switch++;
937 }
938 }
939
940 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700941 list_for_each(node, &adev->usecase_list) {
942 usecase = node_to_item(node, struct audio_usecase, list);
943 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700944 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700945 }
946 }
947
948 list_for_each(node, &adev->usecase_list) {
949 usecase = node_to_item(node, struct audio_usecase, list);
950 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700951 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700952 }
953 }
954
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700955 /* Re-route all the usecases on the shared backend other than the
956 specified usecase to new snd devices */
957 list_for_each(node, &adev->usecase_list) {
958 usecase = node_to_item(node, struct audio_usecase, list);
959 /* Update the in_snd_device only before enabling the audio route */
960 if (switch_device[usecase->id] ) {
961 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700962 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700963 }
964 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700965 }
966}
967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700969static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800970{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700971 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700972 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973
974 switch (channels) {
975 /*
976 * Do not handle stereo output in Multi-channel cases
977 * Stereo case is handled in normal playback path
978 */
979 case 6:
980 ALOGV("%s: HDMI supports 5.1", __func__);
981 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
982 break;
983 case 8:
984 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
985 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
986 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
987 break;
988 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700989 ALOGE("HDMI does not support multi channel playback");
990 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800991 break;
992 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700993 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994}
995
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700996static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
997 uint32_t *supported_sample_rates __unused,
998 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800999{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001000 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
1001 supported_sample_rates,
1002 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001003#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -07001004 for (ssize_t i=0; i<count; i++) {
1005 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1006 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001007 }
1008#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001009 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001010}
1011
Haynes Mathew George569b7482017-05-08 14:44:27 -07001012static int read_usb_sup_channel_masks(bool is_playback,
1013 audio_channel_mask_t *supported_channel_masks,
1014 uint32_t max_masks __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001015{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001016 int channels = audio_extn_usb_get_max_channels(is_playback);
1017 if (is_playback) {
1018 supported_channel_masks[0] =
1019 channels < 3 ? audio_channel_out_mask_from_count(channels) :
1020 audio_channel_mask_for_index_assignment_from_count(channels);
1021 } else {
1022 supported_channel_masks[0] = audio_channel_in_mask_from_count(channels);
1023 }
1024 ALOGV("%s: %s supported ch %d", __func__,
1025 is_playback ? "P" : "C", channels);
1026 return 1;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001027}
1028
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001029static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001030 audio_format_t *supported_formats,
1031 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001032{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001033 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001034 switch (bitwidth) {
1035 case 24:
1036 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001037 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001038 break;
1039 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001040 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001041 break;
1042 case 16:
1043 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001044 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001045 break;
1046 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001047 ALOGV("%s: %s supported format %d", __func__,
1048 is_playback ? "P" : "C", bitwidth);
1049 return 1;
1050}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001051
Haynes Mathew George569b7482017-05-08 14:44:27 -07001052static int read_usb_sup_params_and_compare(bool is_playback,
1053 audio_format_t *format,
1054 audio_format_t *supported_formats,
1055 uint32_t max_formats,
1056 audio_channel_mask_t *mask,
1057 audio_channel_mask_t *supported_channel_masks,
1058 uint32_t max_masks,
1059 uint32_t *rate,
1060 uint32_t *supported_sample_rates,
1061 uint32_t max_rates) {
1062 int ret = 0;
1063 int num_formats;
1064 int num_masks;
1065 int num_rates;
1066 int i;
1067
1068 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1069 max_formats);
1070 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1071 max_masks);
1072 num_rates = read_usb_sup_sample_rates(is_playback,
1073 supported_sample_rates, max_rates);
1074
1075#define LUT(table, len, what, dflt) \
1076 for (i=0; i<len && (table[i] != what); i++); \
1077 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1078
1079 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1080 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1081 LUT(supported_sample_rates, num_rates, *rate, 0);
1082
1083#undef LUT
1084 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001085}
1086
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001087static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1088{
1089 struct audio_usecase *usecase;
1090 struct listnode *node;
1091
1092 list_for_each(node, &adev->usecase_list) {
1093 usecase = node_to_item(node, struct audio_usecase, list);
1094 if (usecase->type == VOICE_CALL) {
1095 ALOGV("%s: usecase id %d", __func__, usecase->id);
1096 return usecase->id;
1097 }
1098 }
1099 return USECASE_INVALID;
1100}
1101
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001102struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1103 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001104{
1105 struct audio_usecase *usecase;
1106 struct listnode *node;
1107
1108 list_for_each(node, &adev->usecase_list) {
1109 usecase = node_to_item(node, struct audio_usecase, list);
1110 if (usecase->id == uc_id)
1111 return usecase;
1112 }
1113 return NULL;
1114}
1115
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001116int select_devices(struct audio_device *adev,
1117 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001118{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001119 snd_device_t out_snd_device = SND_DEVICE_NONE;
1120 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001121 struct audio_usecase *usecase = NULL;
1122 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001123 struct audio_usecase *hfp_usecase = NULL;
1124 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001125 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001126 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001128 usecase = get_usecase_from_list(adev, uc_id);
1129 if (usecase == NULL) {
1130 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1131 return -EINVAL;
1132 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001134 if ((usecase->type == VOICE_CALL) ||
1135 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001136 out_snd_device = platform_get_output_snd_device(adev->platform,
1137 usecase->stream.out->devices);
1138 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001139 usecase->devices = usecase->stream.out->devices;
1140 } else {
1141 /*
1142 * If the voice call is active, use the sound devices of voice call usecase
1143 * so that it would not result any device switch. All the usecases will
1144 * be switched to new device when select_devices() is called for voice call
1145 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001146 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001147 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001148 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001149 vc_usecase = get_usecase_from_list(adev,
1150 get_voice_usecase_id_from_list(adev));
1151 if ((vc_usecase != NULL) &&
1152 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1153 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001154 in_snd_device = vc_usecase->in_snd_device;
1155 out_snd_device = vc_usecase->out_snd_device;
1156 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001157 } else if (audio_extn_hfp_is_active(adev)) {
1158 hfp_ucid = audio_extn_hfp_get_usecase();
1159 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1160 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1161 in_snd_device = hfp_usecase->in_snd_device;
1162 out_snd_device = hfp_usecase->out_snd_device;
1163 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001164 }
1165 if (usecase->type == PCM_PLAYBACK) {
1166 usecase->devices = usecase->stream.out->devices;
1167 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001168 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001169 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001170 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001171 if (usecase->stream.out == adev->primary_output &&
1172 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001173 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1174 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001175 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001176 select_devices(adev, adev->active_input->usecase);
1177 }
1178 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001179 } else if (usecase->type == PCM_CAPTURE) {
1180 usecase->devices = usecase->stream.in->device;
1181 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001182 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001183 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001184 if (adev->active_input &&
1185 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1186 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001187 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001188 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1189 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1190 } else if (adev->primary_output) {
1191 out_device = adev->primary_output->devices;
1192 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001193 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001194 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001195 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001196 }
1197 }
1198
1199 if (out_snd_device == usecase->out_snd_device &&
1200 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001201 return 0;
1202 }
1203
Eric Laurent2bafff12016-03-17 12:17:23 -07001204 if (out_snd_device != SND_DEVICE_NONE &&
1205 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1206 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1207 __func__,
1208 use_case_table[uc_id],
1209 adev->last_logged_snd_device[uc_id][0],
1210 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1211 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1212 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1213 -1,
1214 out_snd_device,
1215 platform_get_snd_device_name(out_snd_device),
1216 platform_get_snd_device_acdb_id(out_snd_device));
1217 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1218 }
1219 if (in_snd_device != SND_DEVICE_NONE &&
1220 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1221 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1222 __func__,
1223 use_case_table[uc_id],
1224 adev->last_logged_snd_device[uc_id][1],
1225 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1226 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1227 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1228 -1,
1229 in_snd_device,
1230 platform_get_snd_device_name(in_snd_device),
1231 platform_get_snd_device_acdb_id(in_snd_device));
1232 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1233 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001234
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001235 /*
1236 * Limitation: While in call, to do a device switch we need to disable
1237 * and enable both RX and TX devices though one of them is same as current
1238 * device.
1239 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001240 if ((usecase->type == VOICE_CALL) &&
1241 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1242 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001243 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001244 /* Disable sidetone only if voice call already exists */
1245 if (voice_is_call_state_active(adev))
1246 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001247 }
1248
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001249 /* Disable current sound devices */
1250 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001251 disable_audio_route(adev, usecase);
1252 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001253 }
1254
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001255 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001256 disable_audio_route(adev, usecase);
1257 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001258 }
1259
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001260 /* Applicable only on the targets that has external modem.
1261 * New device information should be sent to modem before enabling
1262 * the devices to reduce in-call device switch time.
1263 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001264 if ((usecase->type == VOICE_CALL) &&
1265 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1266 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001267 status = platform_switch_voice_call_enable_device_config(adev->platform,
1268 out_snd_device,
1269 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001270 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001271
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001272 /* Enable new sound devices */
1273 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001274 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001275 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001276 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001277 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001278 }
1279
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001280 if (in_snd_device != SND_DEVICE_NONE) {
1281 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001282 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001283 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001284
Eric Laurentb23d5282013-05-14 15:27:20 -07001285 if (usecase->type == VOICE_CALL)
1286 status = platform_switch_voice_call_device_post(adev->platform,
1287 out_snd_device,
1288 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001289
sangwoo170731f2013-06-08 15:36:36 +09001290 usecase->in_snd_device = in_snd_device;
1291 usecase->out_snd_device = out_snd_device;
1292
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001293 audio_extn_tfa_98xx_set_mode();
1294
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001295 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001296
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001297 /* Applicable only on the targets that has external modem.
1298 * Enable device command should be sent to modem only after
1299 * enabling voice call mixer controls
1300 */
vivek mehta765eb642015-08-07 19:46:06 -07001301 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001302 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1303 out_snd_device,
1304 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001305 /* Enable sidetone only if voice call already exists */
1306 if (voice_is_call_state_active(adev))
1307 voice_set_sidetone(adev, out_snd_device, true);
1308 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001309
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 return status;
1311}
1312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001313static int stop_input_stream(struct stream_in *in)
1314{
1315 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001316 struct audio_usecase *uc_info;
1317 struct audio_device *adev = in->dev;
1318
Eric Laurentc8400632013-02-14 19:04:54 -08001319 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001320
Eric Laurent994a6932013-07-17 11:51:42 -07001321 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001322 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001323 uc_info = get_usecase_from_list(adev, in->usecase);
1324 if (uc_info == NULL) {
1325 ALOGE("%s: Could not find the usecase (%d) in the list",
1326 __func__, in->usecase);
1327 return -EINVAL;
1328 }
1329
vivek mehta781065c2017-04-04 12:55:01 -07001330 /* Close in-call recording streams */
1331 voice_check_and_stop_incall_rec_usecase(adev, in);
1332
Eric Laurent150dbfe2013-02-27 14:31:02 -08001333 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001334 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001335
1336 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001337 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001338
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001339 list_remove(&uc_info->list);
1340 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001341
Eric Laurent994a6932013-07-17 11:51:42 -07001342 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001343 return ret;
1344}
1345
1346int start_input_stream(struct stream_in *in)
1347{
1348 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001349 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350 struct audio_usecase *uc_info;
1351 struct audio_device *adev = in->dev;
1352
Eric Laurent994a6932013-07-17 11:51:42 -07001353 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001354
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001355 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1356 return -EIO;
1357
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001358 if (in->card_status == CARD_STATUS_OFFLINE ||
1359 adev->card_status == CARD_STATUS_OFFLINE) {
1360 ALOGW("in->card_status or adev->card_status offline, try again");
1361 ret = -EAGAIN;
1362 goto error_config;
1363 }
1364
vivek mehta781065c2017-04-04 12:55:01 -07001365 /* Check if source matches incall recording usecase criteria */
1366 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1367 if (ret)
1368 goto error_config;
1369 else
1370 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1371
Eric Laurentb23d5282013-05-14 15:27:20 -07001372 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001373 if (in->pcm_device_id < 0) {
1374 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1375 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001376 ret = -EINVAL;
1377 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001378 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001379
1380 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001381 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1382 uc_info->id = in->usecase;
1383 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001384 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001385 uc_info->devices = in->device;
1386 uc_info->in_snd_device = SND_DEVICE_NONE;
1387 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001389 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001390
1391 audio_extn_perf_lock_acquire();
1392
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001393 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001394
Eric Laurent0e46adf2016-12-16 12:49:24 -08001395 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001396 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001397 ALOGE("%s: pcm stream not ready", __func__);
1398 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001399 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001400 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001401 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001402 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1403 goto error_open;
1404 }
1405 } else {
1406 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1407 unsigned int pcm_open_retry_count = 0;
1408
1409 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1410 flags |= PCM_MMAP | PCM_NOIRQ;
1411 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1412 } else if (in->realtime) {
1413 flags |= PCM_MMAP | PCM_NOIRQ;
1414 }
1415
1416 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1417 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1418
1419 while (1) {
1420 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1421 flags, &in->config);
1422 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1423 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1424 if (in->pcm != NULL) {
1425 pcm_close(in->pcm);
1426 in->pcm = NULL;
1427 }
1428 if (pcm_open_retry_count-- == 0) {
1429 ret = -EIO;
1430 goto error_open;
1431 }
1432 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1433 continue;
1434 }
1435 break;
1436 }
1437
1438 ALOGV("%s: pcm_prepare", __func__);
1439 ret = pcm_prepare(in->pcm);
1440 if (ret < 0) {
1441 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001442 pcm_close(in->pcm);
1443 in->pcm = NULL;
1444 goto error_open;
1445 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001446 if (in->realtime) {
1447 ret = pcm_start(in->pcm);
1448 if (ret < 0) {
1449 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1450 pcm_close(in->pcm);
1451 in->pcm = NULL;
1452 goto error_open;
1453 }
1454 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001455 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001456 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001457 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001458 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001459
Eric Laurent0e46adf2016-12-16 12:49:24 -08001460 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001461
1462error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001464 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001465
1466error_config:
1467 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001468 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001469 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001470}
1471
Eric Laurenta1478072015-09-21 17:21:52 -07001472void lock_input_stream(struct stream_in *in)
1473{
1474 pthread_mutex_lock(&in->pre_lock);
1475 pthread_mutex_lock(&in->lock);
1476 pthread_mutex_unlock(&in->pre_lock);
1477}
1478
1479void lock_output_stream(struct stream_out *out)
1480{
1481 pthread_mutex_lock(&out->pre_lock);
1482 pthread_mutex_lock(&out->lock);
1483 pthread_mutex_unlock(&out->pre_lock);
1484}
1485
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001486/* must be called with out->lock locked */
1487static int send_offload_cmd_l(struct stream_out* out, int command)
1488{
1489 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1490
1491 ALOGVV("%s %d", __func__, command);
1492
1493 cmd->cmd = command;
1494 list_add_tail(&out->offload_cmd_list, &cmd->node);
1495 pthread_cond_signal(&out->offload_cond);
1496 return 0;
1497}
1498
1499/* must be called iwth out->lock locked */
1500static void stop_compressed_output_l(struct stream_out *out)
1501{
1502 out->offload_state = OFFLOAD_STATE_IDLE;
1503 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001504 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001505 if (out->compr != NULL) {
1506 compress_stop(out->compr);
1507 while (out->offload_thread_blocked) {
1508 pthread_cond_wait(&out->cond, &out->lock);
1509 }
1510 }
1511}
1512
1513static void *offload_thread_loop(void *context)
1514{
1515 struct stream_out *out = (struct stream_out *) context;
1516 struct listnode *item;
1517
1518 out->offload_state = OFFLOAD_STATE_IDLE;
1519 out->playback_started = 0;
1520
1521 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1522 set_sched_policy(0, SP_FOREGROUND);
1523 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1524
1525 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001526 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001527 for (;;) {
1528 struct offload_cmd *cmd = NULL;
1529 stream_callback_event_t event;
1530 bool send_callback = false;
1531
1532 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1533 __func__, list_empty(&out->offload_cmd_list),
1534 out->offload_state);
1535 if (list_empty(&out->offload_cmd_list)) {
1536 ALOGV("%s SLEEPING", __func__);
1537 pthread_cond_wait(&out->offload_cond, &out->lock);
1538 ALOGV("%s RUNNING", __func__);
1539 continue;
1540 }
1541
1542 item = list_head(&out->offload_cmd_list);
1543 cmd = node_to_item(item, struct offload_cmd, node);
1544 list_remove(item);
1545
1546 ALOGVV("%s STATE %d CMD %d out->compr %p",
1547 __func__, out->offload_state, cmd->cmd, out->compr);
1548
1549 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1550 free(cmd);
1551 break;
1552 }
1553
1554 if (out->compr == NULL) {
1555 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001556 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001557 pthread_cond_signal(&out->cond);
1558 continue;
1559 }
1560 out->offload_thread_blocked = true;
1561 pthread_mutex_unlock(&out->lock);
1562 send_callback = false;
1563 switch(cmd->cmd) {
1564 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1565 compress_wait(out->compr, -1);
1566 send_callback = true;
1567 event = STREAM_CBK_EVENT_WRITE_READY;
1568 break;
1569 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001570 compress_next_track(out->compr);
1571 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001572 send_callback = true;
1573 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001574 /* Resend the metadata for next iteration */
1575 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001576 break;
1577 case OFFLOAD_CMD_DRAIN:
1578 compress_drain(out->compr);
1579 send_callback = true;
1580 event = STREAM_CBK_EVENT_DRAIN_READY;
1581 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001582 case OFFLOAD_CMD_ERROR:
1583 send_callback = true;
1584 event = STREAM_CBK_EVENT_ERROR;
1585 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001586 default:
1587 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1588 break;
1589 }
Eric Laurenta1478072015-09-21 17:21:52 -07001590 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001591 out->offload_thread_blocked = false;
1592 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001593 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001594 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001595 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001596 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001597 free(cmd);
1598 }
1599
1600 pthread_cond_signal(&out->cond);
1601 while (!list_empty(&out->offload_cmd_list)) {
1602 item = list_head(&out->offload_cmd_list);
1603 list_remove(item);
1604 free(node_to_item(item, struct offload_cmd, node));
1605 }
1606 pthread_mutex_unlock(&out->lock);
1607
1608 return NULL;
1609}
1610
1611static int create_offload_callback_thread(struct stream_out *out)
1612{
1613 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1614 list_init(&out->offload_cmd_list);
1615 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1616 offload_thread_loop, out);
1617 return 0;
1618}
1619
1620static int destroy_offload_callback_thread(struct stream_out *out)
1621{
Eric Laurenta1478072015-09-21 17:21:52 -07001622 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001623 stop_compressed_output_l(out);
1624 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1625
1626 pthread_mutex_unlock(&out->lock);
1627 pthread_join(out->offload_thread, (void **) NULL);
1628 pthread_cond_destroy(&out->offload_cond);
1629
1630 return 0;
1631}
1632
Eric Laurent07eeafd2013-10-06 12:52:49 -07001633static bool allow_hdmi_channel_config(struct audio_device *adev)
1634{
1635 struct listnode *node;
1636 struct audio_usecase *usecase;
1637 bool ret = true;
1638
1639 list_for_each(node, &adev->usecase_list) {
1640 usecase = node_to_item(node, struct audio_usecase, list);
1641 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1642 /*
1643 * If voice call is already existing, do not proceed further to avoid
1644 * disabling/enabling both RX and TX devices, CSD calls, etc.
1645 * Once the voice call done, the HDMI channels can be configured to
1646 * max channels of remaining use cases.
1647 */
1648 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001649 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001650 __func__);
1651 ret = false;
1652 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001653 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1654 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001655 "no change in HDMI channels", __func__);
1656 ret = false;
1657 break;
1658 }
1659 }
1660 }
1661 return ret;
1662}
1663
1664static int check_and_set_hdmi_channels(struct audio_device *adev,
1665 unsigned int channels)
1666{
1667 struct listnode *node;
1668 struct audio_usecase *usecase;
1669
1670 /* Check if change in HDMI channel config is allowed */
1671 if (!allow_hdmi_channel_config(adev))
1672 return 0;
1673
1674 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001675 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001676 return 0;
1677 }
1678
1679 platform_set_hdmi_channels(adev->platform, channels);
1680 adev->cur_hdmi_channels = channels;
1681
1682 /*
1683 * Deroute all the playback streams routed to HDMI so that
1684 * the back end is deactivated. Note that backend will not
1685 * be deactivated if any one stream is connected to it.
1686 */
1687 list_for_each(node, &adev->usecase_list) {
1688 usecase = node_to_item(node, struct audio_usecase, list);
1689 if (usecase->type == PCM_PLAYBACK &&
1690 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001691 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001692 }
1693 }
1694
1695 /*
1696 * Enable all the streams disabled above. Now the HDMI backend
1697 * will be activated with new channel configuration
1698 */
1699 list_for_each(node, &adev->usecase_list) {
1700 usecase = node_to_item(node, struct audio_usecase, list);
1701 if (usecase->type == PCM_PLAYBACK &&
1702 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001703 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001704 }
1705 }
1706
1707 return 0;
1708}
1709
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710static int stop_output_stream(struct stream_out *out)
1711{
1712 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713 struct audio_usecase *uc_info;
1714 struct audio_device *adev = out->dev;
1715
Eric Laurent994a6932013-07-17 11:51:42 -07001716 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001717 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718 uc_info = get_usecase_from_list(adev, out->usecase);
1719 if (uc_info == NULL) {
1720 ALOGE("%s: Could not find the usecase (%d) in the list",
1721 __func__, out->usecase);
1722 return -EINVAL;
1723 }
1724
Haynes Mathew George41f86652014-06-17 14:22:15 -07001725 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1726 if (adev->visualizer_stop_output != NULL)
1727 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1728 if (adev->offload_effects_stop_output != NULL)
1729 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1730 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001731
Eric Laurent150dbfe2013-02-27 14:31:02 -08001732 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001733 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001734
1735 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001736 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001738 list_remove(&uc_info->list);
1739 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001740
Eric Laurent0499d4f2014-08-25 22:39:29 -05001741 audio_extn_extspk_update(adev->extspk);
1742
Eric Laurent07eeafd2013-10-06 12:52:49 -07001743 /* Must be called after removing the usecase from list */
1744 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1745 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1746
Eric Laurent994a6932013-07-17 11:51:42 -07001747 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 return ret;
1749}
1750
1751int start_output_stream(struct stream_out *out)
1752{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001754 struct audio_usecase *uc_info;
1755 struct audio_device *adev = out->dev;
1756
Eric Laurent994a6932013-07-17 11:51:42 -07001757 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001758 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001759
1760 if (out->card_status == CARD_STATUS_OFFLINE ||
1761 adev->card_status == CARD_STATUS_OFFLINE) {
1762 ALOGW("out->card_status or adev->card_status offline, try again");
1763 ret = -EAGAIN;
1764 goto error_config;
1765 }
1766
Eric Laurentb23d5282013-05-14 15:27:20 -07001767 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 if (out->pcm_device_id < 0) {
1769 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1770 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001771 ret = -EINVAL;
1772 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 }
1774
1775 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1776 uc_info->id = out->usecase;
1777 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001778 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001779 uc_info->devices = out->devices;
1780 uc_info->in_snd_device = SND_DEVICE_NONE;
1781 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782
Eric Laurent07eeafd2013-10-06 12:52:49 -07001783 /* This must be called before adding this usecase to the list */
1784 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1785 check_and_set_hdmi_channels(adev, out->config.channels);
1786
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001787 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001789 audio_extn_perf_lock_acquire();
1790
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001791 select_devices(adev, out->usecase);
1792
Eric Laurent0499d4f2014-08-25 22:39:29 -05001793 audio_extn_extspk_update(adev->extspk);
1794
Andy Hung31aca912014-03-20 17:14:59 -07001795 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001796 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001797 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1798 out->pcm = NULL;
1799 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1800 COMPRESS_IN, &out->compr_config);
1801 if (out->compr && !is_compress_ready(out->compr)) {
1802 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1803 compress_close(out->compr);
1804 out->compr = NULL;
1805 ret = -EIO;
1806 goto error_open;
1807 }
1808 if (out->offload_callback)
1809 compress_nonblock(out->compr, out->non_blocking);
1810
1811 if (adev->visualizer_start_output != NULL)
1812 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1813 if (adev->offload_effects_start_output != NULL)
1814 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1815 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001816 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001817 ALOGE("%s: pcm stream not ready", __func__);
1818 goto error_open;
1819 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001820 ret = pcm_start(out->pcm);
1821 if (ret < 0) {
1822 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1823 goto error_open;
1824 }
1825 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001826 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001827 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001828
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001829 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1830 flags |= PCM_MMAP | PCM_NOIRQ;
1831 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001832 } else if (out->realtime) {
1833 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001834 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001835
1836 while (1) {
1837 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1838 flags, &out->config);
1839 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1840 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1841 if (out->pcm != NULL) {
1842 pcm_close(out->pcm);
1843 out->pcm = NULL;
1844 }
1845 if (pcm_open_retry_count-- == 0) {
1846 ret = -EIO;
1847 goto error_open;
1848 }
1849 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1850 continue;
1851 }
1852 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001853 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001854 ALOGV("%s: pcm_prepare", __func__);
1855 if (pcm_is_ready(out->pcm)) {
1856 ret = pcm_prepare(out->pcm);
1857 if (ret < 0) {
1858 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1859 pcm_close(out->pcm);
1860 out->pcm = NULL;
1861 goto error_open;
1862 }
1863 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001864 if (out->realtime) {
1865 ret = pcm_start(out->pcm);
1866 if (ret < 0) {
1867 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1868 pcm_close(out->pcm);
1869 out->pcm = NULL;
1870 goto error_open;
1871 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001872 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001873 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001874 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001875 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001876 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001877 audio_extn_utils_send_app_type_gain(out->dev,
1878 out->app_type_cfg.app_type,
1879 &out->app_type_cfg.gain[0]);
vivek mehtae59cfb22017-06-16 15:57:11 -07001880
1881 // consider a scenario where on pause lower layers are tear down.
1882 // so on resume, swap mixer control need to be sent only when
1883 // backend is active, hence rather than sending from enable device
1884 // sending it from start of streamtream
1885
1886 platform_set_swap_channels(adev, true);
1887
Eric Laurent994a6932013-07-17 11:51:42 -07001888 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001889 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001890error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001891 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001892 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001893error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001894 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001895}
1896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897static int check_input_parameters(uint32_t sample_rate,
1898 audio_format_t format,
1899 int channel_count)
1900{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001901 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1902 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
1903 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED)) {
vivek mehtadae44712015-07-27 14:13:18 -07001904 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1905 return -EINVAL;
1906 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001907
vivek mehtadae44712015-07-27 14:13:18 -07001908 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001909 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001910 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1911 return -EINVAL;
1912 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001913
1914 switch (sample_rate) {
1915 case 8000:
1916 case 11025:
1917 case 12000:
1918 case 16000:
1919 case 22050:
1920 case 24000:
1921 case 32000:
1922 case 44100:
1923 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001924 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925 break;
1926 default:
vivek mehtadae44712015-07-27 14:13:18 -07001927 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928 return -EINVAL;
1929 }
1930
1931 return 0;
1932}
1933
vivek mehtaa68fea62017-06-08 19:04:02 -07001934static size_t get_stream_buffer_size(size_t duration_ms,
1935 uint32_t sample_rate,
1936 audio_format_t format,
1937 int channel_count,
1938 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001939{
1940 size_t size = 0;
1941
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001942 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1943 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001944
vivek mehtaa68fea62017-06-08 19:04:02 -07001945 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001946 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001947 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001948
1949 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950
Glenn Kasten4f993392014-05-14 07:30:48 -07001951 /* make sure the size is multiple of 32 bytes
1952 * At 48 kHz mono 16-bit PCM:
1953 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1954 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1955 */
1956 size += 0x1f;
1957 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001958
1959 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960}
1961
1962static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1963{
1964 struct stream_out *out = (struct stream_out *)stream;
1965
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001966 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967}
1968
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001969static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970{
1971 return -ENOSYS;
1972}
1973
1974static size_t out_get_buffer_size(const struct audio_stream *stream)
1975{
1976 struct stream_out *out = (struct stream_out *)stream;
1977
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001978 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1979 return out->compr_config.fragment_size;
1980 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001981 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001982 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983}
1984
1985static uint32_t out_get_channels(const struct audio_stream *stream)
1986{
1987 struct stream_out *out = (struct stream_out *)stream;
1988
1989 return out->channel_mask;
1990}
1991
1992static audio_format_t out_get_format(const struct audio_stream *stream)
1993{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001994 struct stream_out *out = (struct stream_out *)stream;
1995
1996 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001997}
1998
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001999static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000{
2001 return -ENOSYS;
2002}
2003
2004static int out_standby(struct audio_stream *stream)
2005{
2006 struct stream_out *out = (struct stream_out *)stream;
2007 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08002008 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002009
Eric Laurent994a6932013-07-17 11:51:42 -07002010 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002011 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012
Eric Laurenta1478072015-09-21 17:21:52 -07002013 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002015 if (adev->adm_deregister_stream)
2016 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002017 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002018 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002019 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2020 if (out->pcm) {
2021 pcm_close(out->pcm);
2022 out->pcm = NULL;
2023 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002024 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002025 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002026 out->playback_started = false;
2027 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002028 } else {
2029 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002030 out->gapless_mdata.encoder_delay = 0;
2031 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002032 if (out->compr != NULL) {
2033 compress_close(out->compr);
2034 out->compr = NULL;
2035 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002036 }
Phil Burkbc991042017-02-24 08:06:44 -08002037 if (do_stop) {
2038 stop_output_stream(out);
2039 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002040 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002041 }
2042 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002043 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 return 0;
2045}
2046
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002047static int out_on_error(struct audio_stream *stream)
2048{
2049 struct stream_out *out = (struct stream_out *)stream;
2050 struct audio_device *adev = out->dev;
2051 bool do_standby = false;
2052
2053 lock_output_stream(out);
2054 if (!out->standby) {
2055 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2056 stop_compressed_output_l(out);
2057 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2058 } else
2059 do_standby = true;
2060 }
2061 pthread_mutex_unlock(&out->lock);
2062
2063 if (do_standby)
2064 return out_standby(&out->stream.common);
2065
2066 return 0;
2067}
2068
Andy Hung7401c7c2016-09-21 12:41:21 -07002069static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070{
Andy Hung7401c7c2016-09-21 12:41:21 -07002071 struct stream_out *out = (struct stream_out *)stream;
2072
2073 // We try to get the lock for consistency,
2074 // but it isn't necessary for these variables.
2075 // If we're not in standby, we may be blocked on a write.
2076 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2077 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2078 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2079
2080 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002081 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002082 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002083
2084 // dump error info
2085 (void)error_log_dump(
2086 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002087 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002088 (void)power_log_dump(
2089 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 return 0;
2091}
2092
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002093static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2094{
2095 int ret = 0;
2096 char value[32];
2097 struct compr_gapless_mdata tmp_mdata;
2098
2099 if (!out || !parms) {
2100 return -EINVAL;
2101 }
2102
2103 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2104 if (ret >= 0) {
2105 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2106 } else {
2107 return -EINVAL;
2108 }
2109
2110 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2111 if (ret >= 0) {
2112 tmp_mdata.encoder_padding = atoi(value);
2113 } else {
2114 return -EINVAL;
2115 }
2116
2117 out->gapless_mdata = tmp_mdata;
2118 out->send_new_metadata = 1;
2119 ALOGV("%s new encoder delay %u and padding %u", __func__,
2120 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2121
2122 return 0;
2123}
2124
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002125static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2126{
2127 return out == adev->primary_output || out == adev->voice_tx_output;
2128}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002129
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2131{
2132 struct stream_out *out = (struct stream_out *)stream;
2133 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002134 struct audio_usecase *usecase;
2135 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136 struct str_parms *parms;
2137 char value[32];
2138 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002139 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002140 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002141
Eric Laurent2e140aa2016-06-30 17:14:46 -07002142 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002143 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 parms = str_parms_create_str(kvpairs);
2145 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2146 if (ret >= 0) {
2147 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002148 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002149 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002150
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002151 /*
2152 * When HDMI cable is unplugged the music playback is paused and
2153 * the policy manager sends routing=0. But the audioflinger
2154 * continues to write data until standby time (3sec).
2155 * As the HDMI core is turned off, the write gets blocked.
2156 * Avoid this by routing audio to speaker until standby.
2157 */
2158 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2159 val == AUDIO_DEVICE_NONE) {
2160 val = AUDIO_DEVICE_OUT_SPEAKER;
2161 }
2162
2163 /*
2164 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002165 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002166 * the select_devices(). But how do we undo this?
2167 *
2168 * For example, music playback is active on headset (deep-buffer usecase)
2169 * and if we go to ringtones and select a ringtone, low-latency usecase
2170 * will be started on headset+speaker. As we can't enable headset+speaker
2171 * and headset devices at the same time, select_devices() switches the music
2172 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2173 * So when the ringtone playback is completed, how do we undo the same?
2174 *
2175 * We are relying on the out_set_parameters() call on deep-buffer output,
2176 * once the ringtone playback is ended.
2177 * NOTE: We should not check if the current devices are same as new devices.
2178 * Because select_devices() must be called to switch back the music
2179 * playback to headset.
2180 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002181 audio_devices_t new_dev = val;
2182 if (new_dev != AUDIO_DEVICE_NONE) {
2183 bool same_dev = out->devices == new_dev;
2184 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002185
Eric Laurenta7657192014-10-09 21:09:33 -07002186 if (output_drives_call(adev, out)) {
2187 if (!voice_is_in_call(adev)) {
2188 if (adev->mode == AUDIO_MODE_IN_CALL) {
2189 adev->current_call_output = out;
2190 ret = voice_start_call(adev);
2191 }
2192 } else {
2193 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002194 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002195 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002196 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002197
2198 if (!out->standby) {
2199 if (!same_dev) {
2200 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002201 // inform adm before actual routing to prevent glitches.
2202 if (adev->adm_on_routing_change) {
2203 adev->adm_on_routing_change(adev->adm_data,
2204 out->handle);
2205 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002206 }
2207 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002208 audio_extn_tfa_98xx_update();
vivek mehtae59cfb22017-06-16 15:57:11 -07002209
2210 // on device switch force swap, lower functions will make sure
2211 // to check if swap is allowed or not.
2212
2213 if (!same_dev)
2214 platform_set_swap_channels(adev, true);
vivek mehta0d3637a2016-07-24 09:32:02 -07002215 }
2216
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002217 }
2218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002220 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002221
2222 /*handles device and call state changes*/
2223 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002224 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002225
2226 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2227 parse_compress_metadata(out, parms);
2228 }
2229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002231 ALOGV("%s: exit: code(%d)", __func__, status);
2232 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233}
2234
Haynes Mathew George569b7482017-05-08 14:44:27 -07002235static bool stream_get_parameter_channels(struct str_parms *query,
2236 struct str_parms *reply,
2237 audio_channel_mask_t *supported_channel_masks) {
2238 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002239 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002241 size_t i, j;
2242
2243 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2244 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245 value[0] = '\0';
2246 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002247 while (supported_channel_masks[i] != 0) {
2248 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2249 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250 if (!first) {
2251 strcat(value, "|");
2252 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002253 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 first = false;
2255 break;
2256 }
2257 }
2258 i++;
2259 }
2260 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, 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_formats(struct str_parms *query,
2266 struct str_parms *reply,
2267 audio_format_t *supported_formats) {
2268 int ret = -1;
2269 char value[256];
2270 int i;
2271
2272 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2273 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002274 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002275 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002276 case AUDIO_FORMAT_PCM_16_BIT:
2277 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2278 break;
2279 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2280 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2281 break;
2282 case AUDIO_FORMAT_PCM_32_BIT:
2283 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2284 break;
2285 default:
2286 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002287 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002288 break;
2289 }
2290 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002291 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002292 return ret >= 0;
2293}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002294
Haynes Mathew George569b7482017-05-08 14:44:27 -07002295static bool stream_get_parameter_rates(struct str_parms *query,
2296 struct str_parms *reply,
2297 uint32_t *supported_sample_rates) {
2298
2299 int i;
2300 char value[256];
2301 int ret = -1;
2302 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2303 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002304 value[0] = '\0';
2305 i=0;
2306 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002307 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002308 int avail = sizeof(value) - cursor;
2309 ret = snprintf(value + cursor, avail, "%s%d",
2310 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002311 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002312 if (ret < 0 || ret >= avail) {
2313 // if cursor is at the last element of the array
2314 // overwrite with \0 is duplicate work as
2315 // snprintf already put a \0 in place.
2316 // else
2317 // we had space to write the '|' at value[cursor]
2318 // (which will be overwritten) or no space to fill
2319 // the first element (=> cursor == 0)
2320 value[cursor] = '\0';
2321 break;
2322 }
2323 cursor += ret;
2324 ++i;
2325 }
2326 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2327 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002328 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002329 return ret >= 0;
2330}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002331
Haynes Mathew George569b7482017-05-08 14:44:27 -07002332static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2333{
2334 struct stream_out *out = (struct stream_out *)stream;
2335 struct str_parms *query = str_parms_create_str(keys);
2336 char *str;
2337 struct str_parms *reply = str_parms_create();
2338 bool replied = false;
2339 ALOGV("%s: enter: keys - %s", __func__, keys);
2340
2341 replied |= stream_get_parameter_channels(query, reply,
2342 &out->supported_channel_masks[0]);
2343 replied |= stream_get_parameter_formats(query, reply,
2344 &out->supported_formats[0]);
2345 replied |= stream_get_parameter_rates(query, reply,
2346 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002347 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002348 str = str_parms_to_str(reply);
2349 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002350 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002351 }
2352 str_parms_destroy(query);
2353 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002354 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002355 return str;
2356}
2357
2358static uint32_t out_get_latency(const struct audio_stream_out *stream)
2359{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002360 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002361 struct stream_out *out = (struct stream_out *)stream;
2362
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2364 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002365 else if ((out->realtime) ||
2366 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002367 // since the buffer won't be filled up faster than realtime,
2368 // return a smaller number
2369 period_ms = (out->af_period_multiplier * out->config.period_size *
2370 1000) / (out->config.rate);
2371 hw_delay = platform_render_latency(out->usecase)/1000;
2372 return period_ms + hw_delay;
2373 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002374
2375 return (out->config.period_count * out->config.period_size * 1000) /
2376 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002377}
2378
2379static int out_set_volume(struct audio_stream_out *stream, float left,
2380 float right)
2381{
Eric Laurenta9024de2013-04-04 09:19:12 -07002382 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 int volume[2];
2384
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002385 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002386 /* only take left channel into account: the API is for stereo anyway */
2387 out->muted = (left == 0.0f);
2388 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002389 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2390 const char *mixer_ctl_name = "Compress Playback Volume";
2391 struct audio_device *adev = out->dev;
2392 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002393 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2394 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002395 /* try with the control based on device id */
2396 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2397 PCM_PLAYBACK);
2398 char ctl_name[128] = {0};
2399 snprintf(ctl_name, sizeof(ctl_name),
2400 "Compress Playback %d Volume", pcm_device_id);
2401 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2402 if (!ctl) {
2403 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2404 return -EINVAL;
2405 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002406 }
2407 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2408 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2409 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2410 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002411 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002412 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2413 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2414 if (!out->standby) {
2415 // if in standby, cached volume will be sent after stream is opened
2416 audio_extn_utils_send_app_type_gain(out->dev,
2417 out->app_type_cfg.app_type,
2418 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002419 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002420 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002421 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002422
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423 return -ENOSYS;
2424}
2425
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002426// note: this call is safe only if the stream_cb is
2427// removed first in close_output_stream (as is done now).
2428static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2429{
2430 if (!stream || !parms)
2431 return;
2432
2433 struct stream_out *out = (struct stream_out *)stream;
2434 struct audio_device *adev = out->dev;
2435
2436 card_status_t status;
2437 int card;
2438 if (parse_snd_card_status(parms, &card, &status) < 0)
2439 return;
2440
2441 pthread_mutex_lock(&adev->lock);
2442 bool valid_cb = (card == adev->snd_card);
2443 pthread_mutex_unlock(&adev->lock);
2444
2445 if (!valid_cb)
2446 return;
2447
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002448 lock_output_stream(out);
2449 if (out->card_status != status)
2450 out->card_status = status;
2451 pthread_mutex_unlock(&out->lock);
2452
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002453 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2454 use_case_table[out->usecase],
2455 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2456
2457 if (status == CARD_STATUS_OFFLINE)
2458 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002459
2460 return;
2461}
2462
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002463#ifdef NO_AUDIO_OUT
2464static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002465 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002466{
2467 struct stream_out *out = (struct stream_out *)stream;
2468
2469 /* No Output device supported other than BT for playback.
2470 * Sleep for the amount of buffer duration
2471 */
Eric Laurenta1478072015-09-21 17:21:52 -07002472 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002473 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2474 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002475 out_get_sample_rate(&out->stream.common));
2476 pthread_mutex_unlock(&out->lock);
2477 return bytes;
2478}
2479#endif
2480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2482 size_t bytes)
2483{
2484 struct stream_out *out = (struct stream_out *)stream;
2485 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002486 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002487 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488
Eric Laurenta1478072015-09-21 17:21:52 -07002489 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002490 // this is always nonzero
2491 const int frame_size = audio_stream_out_frame_size(stream);
2492
Eric Laurent0e46adf2016-12-16 12:49:24 -08002493 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2494 error_code = ERROR_CODE_WRITE;
2495 goto exit;
2496 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002498 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002499 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002501 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002502 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002504 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002505 goto exit;
2506 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002507
2508 if (last_known_cal_step != -1) {
2509 ALOGD("%s: retry previous failed cal level set", __func__);
2510 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2511 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002514 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002515 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002516 if (out->send_new_metadata) {
2517 ALOGVV("send new gapless metadata");
2518 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2519 out->send_new_metadata = 0;
2520 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002521 unsigned int avail;
2522 struct timespec tstamp;
2523 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2524 /* Do not limit write size if the available frames count is unknown */
2525 if (ret != 0) {
2526 avail = bytes;
2527 }
2528 if (avail == 0) {
2529 ret = 0;
2530 } else {
2531 if (avail > bytes) {
2532 avail = bytes;
2533 }
2534 ret = compress_write(out->compr, buffer, avail);
2535 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2536 __func__, avail, ret);
2537 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002538
Eric Laurent6e895242013-09-05 16:10:57 -07002539 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002540 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2541 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002542 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002543 compress_start(out->compr);
2544 out->playback_started = 1;
2545 out->offload_state = OFFLOAD_STATE_PLAYING;
2546 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002547 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002548 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002549 } else {
2550 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002551 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002552 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002553 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002554 return ret;
2555 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002556 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002557 if (out->pcm) {
2558 if (out->muted)
2559 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002560
Eric Laurent0e46adf2016-12-16 12:49:24 -08002561 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002562
Haynes Mathew George03c40102016-01-29 17:57:48 -08002563 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2564 out->config.rate;
2565 request_out_focus(out, ns);
2566
2567 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2568 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002569 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002570 else
2571 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002572
Haynes Mathew George03c40102016-01-29 17:57:48 -08002573 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002574 } else {
2575 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002576 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002577 }
2578
2579exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002580 // For PCM we always consume the buffer and return #bytes regardless of ret.
2581 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2582 out->written += bytes / (out->config.channels * sizeof(short));
2583 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002584 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002585
2586 // only get time if needed for logging, as it is a system call on 32 bit devices.
2587 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2588 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2589 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002590
Andy Hung7401c7c2016-09-21 12:41:21 -07002591 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002592 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002593 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2594 ALOGE_IF(out->pcm != NULL,
2595 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002596 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002597 out_get_sample_rate(&out->stream.common);
2598 // usleep not guaranteed for values over 1 second but we don't limit here.
2599 }
2600 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 pthread_mutex_unlock(&out->lock);
2603
2604 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002605 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002606 if (sleeptime_us != 0)
2607 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002608 } else {
2609 // only log if the data is properly written (out->power_log may be null)
2610 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 }
2612 return bytes;
2613}
2614
2615static int out_get_render_position(const struct audio_stream_out *stream,
2616 uint32_t *dsp_frames)
2617{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002618 struct stream_out *out = (struct stream_out *)stream;
2619 *dsp_frames = 0;
2620 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002621 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002622 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002623 unsigned long frames = 0;
2624 // TODO: check return value
2625 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2626 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002627 ALOGVV("%s rendered frames %d sample_rate %d",
2628 __func__, *dsp_frames, out->sample_rate);
2629 }
2630 pthread_mutex_unlock(&out->lock);
2631 return 0;
2632 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002633 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634}
2635
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002636static int out_add_audio_effect(const struct audio_stream *stream __unused,
2637 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638{
2639 return 0;
2640}
2641
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002642static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2643 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644{
2645 return 0;
2646}
2647
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002648static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2649 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002651 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652}
2653
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002654static int out_get_presentation_position(const struct audio_stream_out *stream,
2655 uint64_t *frames, struct timespec *timestamp)
2656{
2657 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002658 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002659 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002660
Eric Laurenta1478072015-09-21 17:21:52 -07002661 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002662
Eric Laurent949a0892013-09-20 09:20:13 -07002663 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2664 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002665 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002666 compress_get_tstamp(out->compr, &dsp_frames,
2667 &out->sample_rate);
2668 ALOGVV("%s rendered frames %ld sample_rate %d",
2669 __func__, dsp_frames, out->sample_rate);
2670 *frames = dsp_frames;
2671 ret = 0;
2672 /* this is the best we can do */
2673 clock_gettime(CLOCK_MONOTONIC, timestamp);
2674 }
2675 } else {
2676 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002677 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002678 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2679 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002680 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002681 // This adjustment accounts for buffering after app processor.
2682 // It is based on estimated DSP latency per use case, rather than exact.
2683 signed_frames -=
2684 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2685
Eric Laurent949a0892013-09-20 09:20:13 -07002686 // It would be unusual for this value to be negative, but check just in case ...
2687 if (signed_frames >= 0) {
2688 *frames = signed_frames;
2689 ret = 0;
2690 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002691 }
2692 }
2693 }
2694
2695 pthread_mutex_unlock(&out->lock);
2696
2697 return ret;
2698}
2699
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002700static int out_set_callback(struct audio_stream_out *stream,
2701 stream_callback_t callback, void *cookie)
2702{
2703 struct stream_out *out = (struct stream_out *)stream;
2704
2705 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002706 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002707 out->offload_callback = callback;
2708 out->offload_cookie = cookie;
2709 pthread_mutex_unlock(&out->lock);
2710 return 0;
2711}
2712
2713static int out_pause(struct audio_stream_out* stream)
2714{
2715 struct stream_out *out = (struct stream_out *)stream;
2716 int status = -ENOSYS;
2717 ALOGV("%s", __func__);
2718 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002719 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002720 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2721 status = compress_pause(out->compr);
2722 out->offload_state = OFFLOAD_STATE_PAUSED;
2723 }
2724 pthread_mutex_unlock(&out->lock);
2725 }
2726 return status;
2727}
2728
2729static int out_resume(struct audio_stream_out* stream)
2730{
2731 struct stream_out *out = (struct stream_out *)stream;
2732 int status = -ENOSYS;
2733 ALOGV("%s", __func__);
2734 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2735 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002736 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002737 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2738 status = compress_resume(out->compr);
2739 out->offload_state = OFFLOAD_STATE_PLAYING;
2740 }
2741 pthread_mutex_unlock(&out->lock);
2742 }
2743 return status;
2744}
2745
2746static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2747{
2748 struct stream_out *out = (struct stream_out *)stream;
2749 int status = -ENOSYS;
2750 ALOGV("%s", __func__);
2751 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002752 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002753 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2754 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2755 else
2756 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2757 pthread_mutex_unlock(&out->lock);
2758 }
2759 return status;
2760}
2761
2762static int out_flush(struct audio_stream_out* stream)
2763{
2764 struct stream_out *out = (struct stream_out *)stream;
2765 ALOGV("%s", __func__);
2766 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002767 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002768 stop_compressed_output_l(out);
2769 pthread_mutex_unlock(&out->lock);
2770 return 0;
2771 }
2772 return -ENOSYS;
2773}
2774
Eric Laurent0e46adf2016-12-16 12:49:24 -08002775static int out_stop(const struct audio_stream_out* stream)
2776{
2777 struct stream_out *out = (struct stream_out *)stream;
2778 struct audio_device *adev = out->dev;
2779 int ret = -ENOSYS;
2780
2781 ALOGV("%s", __func__);
2782 pthread_mutex_lock(&adev->lock);
2783 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2784 out->playback_started && out->pcm != NULL) {
2785 pcm_stop(out->pcm);
2786 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002787 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002788 }
2789 pthread_mutex_unlock(&adev->lock);
2790 return ret;
2791}
2792
2793static int out_start(const struct audio_stream_out* stream)
2794{
2795 struct stream_out *out = (struct stream_out *)stream;
2796 struct audio_device *adev = out->dev;
2797 int ret = -ENOSYS;
2798
2799 ALOGV("%s", __func__);
2800 pthread_mutex_lock(&adev->lock);
2801 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2802 !out->playback_started && out->pcm != NULL) {
2803 ret = start_output_stream(out);
2804 if (ret == 0) {
2805 out->playback_started = true;
2806 }
2807 }
2808 pthread_mutex_unlock(&adev->lock);
2809 return ret;
2810}
2811
Phil Burkbc991042017-02-24 08:06:44 -08002812/*
2813 * Modify config->period_count based on min_size_frames
2814 */
2815static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2816{
2817 int periodCountRequested = (min_size_frames + config->period_size - 1)
2818 / config->period_size;
2819 int periodCount = MMAP_PERIOD_COUNT_MIN;
2820
2821 ALOGV("%s original config.period_size = %d config.period_count = %d",
2822 __func__, config->period_size, config->period_count);
2823
2824 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2825 periodCount *= 2;
2826 }
2827 config->period_count = periodCount;
2828
2829 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2830}
2831
Eric Laurent0e46adf2016-12-16 12:49:24 -08002832static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2833 int32_t min_size_frames,
2834 struct audio_mmap_buffer_info *info)
2835{
2836 struct stream_out *out = (struct stream_out *)stream;
2837 struct audio_device *adev = out->dev;
2838 int ret = 0;
2839 unsigned int offset1;
2840 unsigned int frames1;
2841 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07002842 uint32_t mmap_size;
2843 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002844
2845 ALOGV("%s", __func__);
2846 pthread_mutex_lock(&adev->lock);
2847
2848 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002849 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002850 ret = -EINVAL;
2851 goto exit;
2852 }
2853 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002854 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002855 ret = -ENOSYS;
2856 goto exit;
2857 }
2858 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2859 if (out->pcm_device_id < 0) {
2860 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2861 __func__, out->pcm_device_id, out->usecase);
2862 ret = -EINVAL;
2863 goto exit;
2864 }
Phil Burkbc991042017-02-24 08:06:44 -08002865
2866 adjust_mmap_period_count(&out->config, min_size_frames);
2867
Eric Laurent0e46adf2016-12-16 12:49:24 -08002868 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2869 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2870 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2871 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2872 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2873 step = "open";
2874 ret = -ENODEV;
2875 goto exit;
2876 }
2877 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2878 if (ret < 0) {
2879 step = "begin";
2880 goto exit;
2881 }
2882 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07002883 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002884 info->burst_size_frames = out->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07002885 ret = platform_get_mmap_data_fd(adev->platform,
2886 out->pcm_device_id, 0 /*playback*/,
2887 &info->shared_memory_fd,
2888 &mmap_size);
2889 if (ret < 0) {
2890 // Fall back to non exclusive mode
2891 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2892 } else {
2893 if (mmap_size < buffer_size) {
2894 step = "mmap";
2895 goto exit;
2896 }
2897 // FIXME: indicate exclusive mode support by returning a negative buffer size
2898 info->buffer_size_frames *= -1;
2899 }
2900 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002901
2902 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2903 if (ret < 0) {
2904 step = "commit";
2905 goto exit;
2906 }
Phil Burkbc991042017-02-24 08:06:44 -08002907
2908 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002909 ret = 0;
2910
2911 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2912 __func__, info->shared_memory_address, info->buffer_size_frames);
2913
2914exit:
2915 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002916 if (out->pcm == NULL) {
2917 ALOGE("%s: %s - %d", __func__, step, ret);
2918 } else {
2919 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002920 pcm_close(out->pcm);
2921 out->pcm = NULL;
2922 }
2923 }
2924 pthread_mutex_unlock(&adev->lock);
2925 return ret;
2926}
2927
2928static int out_get_mmap_position(const struct audio_stream_out *stream,
2929 struct audio_mmap_position *position)
2930{
2931 struct stream_out *out = (struct stream_out *)stream;
2932 ALOGVV("%s", __func__);
2933 if (position == NULL) {
2934 return -EINVAL;
2935 }
2936 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2937 return -ENOSYS;
2938 }
2939 if (out->pcm == NULL) {
2940 return -ENOSYS;
2941 }
2942
2943 struct timespec ts = { 0, 0 };
2944 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2945 if (ret < 0) {
2946 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2947 return ret;
2948 }
Andy Hungfc044e12017-03-20 09:24:22 -07002949 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002950 return 0;
2951}
2952
2953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954/** audio_stream_in implementation **/
2955static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2956{
2957 struct stream_in *in = (struct stream_in *)stream;
2958
2959 return in->config.rate;
2960}
2961
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002962static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002963{
2964 return -ENOSYS;
2965}
2966
2967static size_t in_get_buffer_size(const struct audio_stream *stream)
2968{
2969 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002970 return in->config.period_size * in->af_period_multiplier *
2971 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002972}
2973
2974static uint32_t in_get_channels(const struct audio_stream *stream)
2975{
2976 struct stream_in *in = (struct stream_in *)stream;
2977
2978 return in->channel_mask;
2979}
2980
vivek mehta4ed66e62016-04-15 23:33:34 -07002981static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002982{
vivek mehta4ed66e62016-04-15 23:33:34 -07002983 struct stream_in *in = (struct stream_in *)stream;
2984 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985}
2986
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002987static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988{
2989 return -ENOSYS;
2990}
2991
2992static int in_standby(struct audio_stream *stream)
2993{
2994 struct stream_in *in = (struct stream_in *)stream;
2995 struct audio_device *adev = in->dev;
2996 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002997 bool do_stop = true;
2998
Eric Laurent994a6932013-07-17 11:51:42 -07002999 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07003000
3001 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003002
3003 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08003004 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003005 audio_extn_sound_trigger_stop_lab(in);
3006 in->standby = true;
3007 }
3008
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003009 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003010 if (adev->adm_deregister_stream)
3011 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
3012
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003013 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003015 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08003016 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003017 in->capture_started = false;
3018 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003019 if (in->pcm) {
3020 pcm_close(in->pcm);
3021 in->pcm = NULL;
3022 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003023 adev->enable_voicerx = false;
3024 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08003025 if (do_stop) {
3026 status = stop_input_stream(in);
3027 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003028 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003029 }
3030 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07003031 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 return status;
3033}
3034
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003035static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036{
3037 return 0;
3038}
3039
3040static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3041{
3042 struct stream_in *in = (struct stream_in *)stream;
3043 struct audio_device *adev = in->dev;
3044 struct str_parms *parms;
3045 char *str;
3046 char value[32];
3047 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003048 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049
Eric Laurent994a6932013-07-17 11:51:42 -07003050 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 parms = str_parms_create_str(kvpairs);
3052
3053 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3054
Eric Laurenta1478072015-09-21 17:21:52 -07003055 lock_input_stream(in);
3056
Eric Laurent150dbfe2013-02-27 14:31:02 -08003057 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 if (ret >= 0) {
3059 val = atoi(value);
3060 /* no audio source uses val == 0 */
3061 if ((in->source != val) && (val != 0)) {
3062 in->source = val;
3063 }
3064 }
3065
3066 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003067
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 if (ret >= 0) {
3069 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003070 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071 in->device = val;
3072 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003073 if (!in->standby) {
3074 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003075 // inform adm before actual routing to prevent glitches.
3076 if (adev->adm_on_routing_change) {
3077 adev->adm_on_routing_change(adev->adm_data,
3078 in->capture_handle);
3079 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003080 select_devices(adev, in->usecase);
3081 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 }
3083 }
3084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003086 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087
3088 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003089 ALOGV("%s: exit: status(%d)", __func__, status);
3090 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091}
3092
Haynes Mathew George569b7482017-05-08 14:44:27 -07003093static char* in_get_parameters(const struct audio_stream *stream,
3094 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003096 struct stream_in *in = (struct stream_in *)stream;
3097 struct str_parms *query = str_parms_create_str(keys);
3098 char *str;
3099 struct str_parms *reply = str_parms_create();
3100 bool replied = false;
3101
3102 ALOGV("%s: enter: keys - %s", __func__, keys);
3103 replied |= stream_get_parameter_channels(query, reply,
3104 &in->supported_channel_masks[0]);
3105 replied |= stream_get_parameter_formats(query, reply,
3106 &in->supported_formats[0]);
3107 replied |= stream_get_parameter_rates(query, reply,
3108 &in->supported_sample_rates[0]);
3109 if (replied) {
3110 str = str_parms_to_str(reply);
3111 } else {
3112 str = strdup(keys);
3113 }
3114 str_parms_destroy(query);
3115 str_parms_destroy(reply);
3116 ALOGV("%s: exit: returns - %s", __func__, str);
3117 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118}
3119
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003120static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003122 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003123}
3124
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003125static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3126{
3127 if (!stream || !parms)
3128 return;
3129
3130 struct stream_in *in = (struct stream_in *)stream;
3131 struct audio_device *adev = in->dev;
3132
3133 card_status_t status;
3134 int card;
3135 if (parse_snd_card_status(parms, &card, &status) < 0)
3136 return;
3137
3138 pthread_mutex_lock(&adev->lock);
3139 bool valid_cb = (card == adev->snd_card);
3140 pthread_mutex_unlock(&adev->lock);
3141
3142 if (!valid_cb)
3143 return;
3144
3145 lock_input_stream(in);
3146 if (in->card_status != status)
3147 in->card_status = status;
3148 pthread_mutex_unlock(&in->lock);
3149
3150 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3151 use_case_table[in->usecase],
3152 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3153
3154 // a better solution would be to report error back to AF and let
3155 // it put the stream to standby
3156 if (status == CARD_STATUS_OFFLINE)
3157 in_standby(&in->stream.common);
3158
3159 return;
3160}
3161
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003162static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3163 size_t bytes)
3164{
3165 struct stream_in *in = (struct stream_in *)stream;
3166 struct audio_device *adev = in->dev;
3167 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003168 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169
Eric Laurenta1478072015-09-21 17:21:52 -07003170 lock_input_stream(in);
3171
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003172 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003173 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003174 /* Read from sound trigger HAL */
3175 audio_extn_sound_trigger_read(in, buffer, bytes);
3176 pthread_mutex_unlock(&in->lock);
3177 return bytes;
3178 }
3179
Eric Laurent0e46adf2016-12-16 12:49:24 -08003180 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3181 ret = -ENOSYS;
3182 goto exit;
3183 }
3184
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003185 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003186 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003188 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 goto exit;
3191 }
3192 in->standby = 0;
3193 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194
Haynes Mathew George03c40102016-01-29 17:57:48 -08003195 //what's the duration requested by the client?
3196 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3197 in->config.rate;
3198 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003199
Haynes Mathew George03c40102016-01-29 17:57:48 -08003200 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003202 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003203 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003204 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003205 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003206 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003207 if (ret < 0) {
3208 ALOGE("Failed to read w/err %s", strerror(errno));
3209 ret = -errno;
3210 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003211 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3212 if (bytes % 4 == 0) {
3213 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3214 int_buf_stream = buffer;
3215 for (size_t itt=0; itt < bytes/4 ; itt++) {
3216 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003217 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003218 } else {
3219 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3220 ret = -EINVAL;
3221 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003222 }
3223 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003224 }
3225
Haynes Mathew George03c40102016-01-29 17:57:48 -08003226 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003227
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228 /*
3229 * Instead of writing zeroes here, we could trust the hardware
3230 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003231 * 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 -08003232 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003233 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234 memset(buffer, 0, bytes);
3235
3236exit:
3237 pthread_mutex_unlock(&in->lock);
3238
3239 if (ret != 0) {
3240 in_standby(&in->stream.common);
3241 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07003242 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003243 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003244 memset(buffer, 0, bytes); // clear return data
3245 }
3246 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08003247 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248 }
3249 return bytes;
3250}
3251
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003252static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253{
3254 return 0;
3255}
3256
Andy Hung6ebe5962016-01-15 17:46:57 -08003257static int in_get_capture_position(const struct audio_stream_in *stream,
3258 int64_t *frames, int64_t *time)
3259{
3260 if (stream == NULL || frames == NULL || time == NULL) {
3261 return -EINVAL;
3262 }
3263 struct stream_in *in = (struct stream_in *)stream;
3264 int ret = -ENOSYS;
3265
3266 lock_input_stream(in);
3267 if (in->pcm) {
3268 struct timespec timestamp;
3269 unsigned int avail;
3270 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3271 *frames = in->frames_read + avail;
3272 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3273 ret = 0;
3274 }
3275 }
3276 pthread_mutex_unlock(&in->lock);
3277 return ret;
3278}
3279
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003280static int add_remove_audio_effect(const struct audio_stream *stream,
3281 effect_handle_t effect,
3282 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003284 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003285 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003286 int status = 0;
3287 effect_descriptor_t desc;
3288
3289 status = (*effect)->get_descriptor(effect, &desc);
3290 if (status != 0)
3291 return status;
3292
Eric Laurenta1478072015-09-21 17:21:52 -07003293 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003294 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003295 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003296 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003297 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003298 in->enable_aec != enable &&
3299 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3300 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003301 if (!enable)
3302 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003303 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3304 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3305 adev->enable_voicerx = enable;
3306 struct audio_usecase *usecase;
3307 struct listnode *node;
3308 list_for_each(node, &adev->usecase_list) {
3309 usecase = node_to_item(node, struct audio_usecase, list);
3310 if (usecase->type == PCM_PLAYBACK) {
3311 select_devices(adev, usecase->id);
3312 break;
3313 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003314 }
3315 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003316 if (!in->standby)
3317 select_devices(in->dev, in->usecase);
3318 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003319 if (in->enable_ns != enable &&
3320 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3321 in->enable_ns = enable;
3322 if (!in->standby)
3323 select_devices(in->dev, in->usecase);
3324 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003325 pthread_mutex_unlock(&in->dev->lock);
3326 pthread_mutex_unlock(&in->lock);
3327
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328 return 0;
3329}
3330
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003331static int in_add_audio_effect(const struct audio_stream *stream,
3332 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333{
Eric Laurent994a6932013-07-17 11:51:42 -07003334 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003335 return add_remove_audio_effect(stream, effect, true);
3336}
3337
3338static int in_remove_audio_effect(const struct audio_stream *stream,
3339 effect_handle_t effect)
3340{
Eric Laurent994a6932013-07-17 11:51:42 -07003341 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003342 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343}
3344
Eric Laurent0e46adf2016-12-16 12:49:24 -08003345static int in_stop(const struct audio_stream_in* stream)
3346{
3347 struct stream_in *in = (struct stream_in *)stream;
3348 struct audio_device *adev = in->dev;
3349
3350 int ret = -ENOSYS;
3351 ALOGV("%s", __func__);
3352 pthread_mutex_lock(&adev->lock);
3353 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3354 in->capture_started && in->pcm != NULL) {
3355 pcm_stop(in->pcm);
3356 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003357 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003358 }
3359 pthread_mutex_unlock(&adev->lock);
3360 return ret;
3361}
3362
3363static int in_start(const struct audio_stream_in* stream)
3364{
3365 struct stream_in *in = (struct stream_in *)stream;
3366 struct audio_device *adev = in->dev;
3367 int ret = -ENOSYS;
3368
3369 ALOGV("%s in %p", __func__, in);
3370 pthread_mutex_lock(&adev->lock);
3371 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3372 !in->capture_started && in->pcm != NULL) {
3373 if (!in->capture_started) {
3374 ret = start_input_stream(in);
3375 if (ret == 0) {
3376 in->capture_started = true;
3377 }
3378 }
3379 }
3380 pthread_mutex_unlock(&adev->lock);
3381 return ret;
3382}
3383
3384static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3385 int32_t min_size_frames,
3386 struct audio_mmap_buffer_info *info)
3387{
3388 struct stream_in *in = (struct stream_in *)stream;
3389 struct audio_device *adev = in->dev;
3390 int ret = 0;
3391 unsigned int offset1;
3392 unsigned int frames1;
3393 const char *step = "";
Haynes Mathew George96483a22017-03-28 14:52:47 -07003394 uint32_t mmap_size;
3395 uint32_t buffer_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003396
3397 pthread_mutex_lock(&adev->lock);
3398 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003399
Eric Laurent0e46adf2016-12-16 12:49:24 -08003400 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003401 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003402 ret = -EINVAL;
3403 goto exit;
3404 }
3405 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003406 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003407 ALOGV("%s in %p", __func__, in);
3408 ret = -ENOSYS;
3409 goto exit;
3410 }
3411 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3412 if (in->pcm_device_id < 0) {
3413 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3414 __func__, in->pcm_device_id, in->usecase);
3415 ret = -EINVAL;
3416 goto exit;
3417 }
Phil Burkbc991042017-02-24 08:06:44 -08003418
3419 adjust_mmap_period_count(&in->config, min_size_frames);
3420
Eric Laurent0e46adf2016-12-16 12:49:24 -08003421 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3422 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3423 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3424 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3425 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3426 step = "open";
3427 ret = -ENODEV;
3428 goto exit;
3429 }
3430
3431 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3432 if (ret < 0) {
3433 step = "begin";
3434 goto exit;
3435 }
3436 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
Haynes Mathew George96483a22017-03-28 14:52:47 -07003437 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003438 info->burst_size_frames = in->config.period_size;
Haynes Mathew George96483a22017-03-28 14:52:47 -07003439 ret = platform_get_mmap_data_fd(adev->platform,
3440 in->pcm_device_id, 1 /*capture*/,
3441 &info->shared_memory_fd,
3442 &mmap_size);
3443 if (ret < 0) {
3444 // Fall back to non exclusive mode
3445 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3446 } else {
3447 if (mmap_size < buffer_size) {
3448 step = "mmap";
3449 goto exit;
3450 }
3451 // FIXME: indicate exclusive mode support by returning a negative buffer size
3452 info->buffer_size_frames *= -1;
3453 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08003454
Haynes Mathew George96483a22017-03-28 14:52:47 -07003455 memset(info->shared_memory_address, 0, buffer_size);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003456
3457 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3458 if (ret < 0) {
3459 step = "commit";
3460 goto exit;
3461 }
3462
Phil Burkbc991042017-02-24 08:06:44 -08003463 in->standby = false;
3464 ret = 0;
3465
Eric Laurent0e46adf2016-12-16 12:49:24 -08003466 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3467 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003468
3469exit:
3470 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003471 if (in->pcm == NULL) {
3472 ALOGE("%s: %s - %d", __func__, step, ret);
3473 } else {
3474 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003475 pcm_close(in->pcm);
3476 in->pcm = NULL;
3477 }
3478 }
3479 pthread_mutex_unlock(&adev->lock);
3480 return ret;
3481}
3482
3483static int in_get_mmap_position(const struct audio_stream_in *stream,
3484 struct audio_mmap_position *position)
3485{
3486 struct stream_in *in = (struct stream_in *)stream;
3487 ALOGVV("%s", __func__);
3488 if (position == NULL) {
3489 return -EINVAL;
3490 }
3491 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3492 return -ENOSYS;
3493 }
3494 if (in->pcm == NULL) {
3495 return -ENOSYS;
3496 }
3497 struct timespec ts = { 0, 0 };
3498 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3499 if (ret < 0) {
3500 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3501 return ret;
3502 }
Andy Hungfc044e12017-03-20 09:24:22 -07003503 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003504 return 0;
3505}
3506
3507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003508static int adev_open_output_stream(struct audio_hw_device *dev,
3509 audio_io_handle_t handle,
3510 audio_devices_t devices,
3511 audio_output_flags_t flags,
3512 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003513 struct audio_stream_out **stream_out,
3514 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515{
3516 struct audio_device *adev = (struct audio_device *)dev;
3517 struct stream_out *out;
3518 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003519 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3520 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3521 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3522 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523
Eric Laurent994a6932013-07-17 11:51:42 -07003524 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525 __func__, config->sample_rate, config->channel_mask, devices, flags);
3526 *stream_out = NULL;
3527 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3528
3529 if (devices == AUDIO_DEVICE_NONE)
3530 devices = AUDIO_DEVICE_OUT_SPEAKER;
3531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532 out->flags = flags;
3533 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003534 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003535 out->format = config->format;
3536 out->sample_rate = config->sample_rate;
3537 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3538 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003539 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540
3541 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003542 if (audio_is_linear_pcm(out->format) &&
3543 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003544 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003545 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003546 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003547 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003548 if (config->sample_rate == 0)
3549 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3550 if (config->channel_mask == 0)
3551 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3552 if (config->format == AUDIO_FORMAT_DEFAULT)
3553 config->format = AUDIO_FORMAT_PCM_16_BIT;
3554 } else if (is_usb_dev) {
3555 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3556 &config->format,
3557 &out->supported_formats[0],
3558 MAX_SUPPORTED_FORMATS,
3559 &config->channel_mask,
3560 &out->supported_channel_masks[0],
3561 MAX_SUPPORTED_CHANNEL_MASKS,
3562 &config->sample_rate,
3563 &out->supported_sample_rates[0],
3564 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003565 ALOGV("plugged dev USB ret %d", ret);
3566 } else {
3567 ret = -1;
3568 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003569 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003570 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003571 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003572
Haynes Mathew George569b7482017-05-08 14:44:27 -07003573 out->channel_mask = config->channel_mask;
3574 out->sample_rate = config->sample_rate;
3575 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003576 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3577 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003578 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003580 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003581 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003582 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003583 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003584 pthread_mutex_lock(&adev->lock);
3585 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3586 pthread_mutex_unlock(&adev->lock);
3587
3588 // reject offload during card offline to allow
3589 // fallback to s/w paths
3590 if (offline) {
3591 ret = -ENODEV;
3592 goto error_open;
3593 }
3594
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003595 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3596 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3597 ALOGE("%s: Unsupported Offload information", __func__);
3598 ret = -EINVAL;
3599 goto error_open;
3600 }
3601 if (!is_supported_format(config->offload_info.format)) {
3602 ALOGE("%s: Unsupported audio format", __func__);
3603 ret = -EINVAL;
3604 goto error_open;
3605 }
3606
3607 out->compr_config.codec = (struct snd_codec *)
3608 calloc(1, sizeof(struct snd_codec));
3609
3610 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3611 if (config->offload_info.channel_mask)
3612 out->channel_mask = config->offload_info.channel_mask;
3613 else if (config->channel_mask)
3614 out->channel_mask = config->channel_mask;
3615 out->format = config->offload_info.format;
3616 out->sample_rate = config->offload_info.sample_rate;
3617
3618 out->stream.set_callback = out_set_callback;
3619 out->stream.pause = out_pause;
3620 out->stream.resume = out_resume;
3621 out->stream.drain = out_drain;
3622 out->stream.flush = out_flush;
3623
3624 out->compr_config.codec->id =
3625 get_snd_codec_id(config->offload_info.format);
3626 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3627 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003628 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003629 out->compr_config.codec->bit_rate =
3630 config->offload_info.bit_rate;
3631 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003632 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003633 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3634
3635 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3636 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003637
3638 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003639 create_offload_callback_thread(out);
3640 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3641 __func__, config->offload_info.version,
3642 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003643 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003644 switch (config->sample_rate) {
3645 case 8000:
3646 case 16000:
3647 case 48000:
3648 out->sample_rate = config->sample_rate;
3649 break;
3650 default:
3651 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003652 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003653 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003654 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3655 out->config = pcm_config_afe_proxy_playback;
3656 adev->voice_tx_output = out;
vivek mehtaa68fea62017-06-08 19:04:02 -07003657 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3658 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3659 AUDIO_OUTPUT_FLAG_VOIP_RX))) {
3660 uint32_t buffer_size, frame_size;
3661 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3662 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3663 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3664 out->config = pcm_config_voip;
3665 out->config.format = pcm_format_from_audio_format(config->format);
3666 out->config.rate = config->sample_rate;
3667 out->config.channels =
3668 audio_channel_count_from_out_mask(config->channel_mask);
3669 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3670 config->sample_rate,
3671 config->format,
3672 out->config.channels,
3673 false /*is_low_latency*/);
3674 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3675 out->config.period_size = buffer_size / frame_size;
3676 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3677 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003678 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003679 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3680 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3681 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003682 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3683 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3684 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003685 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3686 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003687 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003688 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003689 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3690 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3691 out->config = pcm_config_mmap_playback;
3692 out->stream.start = out_start;
3693 out->stream.stop = out_stop;
3694 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3695 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003696 } else {
3697 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3698 out->config = pcm_config_low_latency;
3699 }
3700 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3701 if (k_enable_extended_precision
3702 && pcm_params_format_test(adev->use_case_table[out->usecase],
3703 pcm_format_from_audio_format(config->format))) {
3704 out->config.format = pcm_format_from_audio_format(config->format);
3705 /* out->format already set to config->format */
3706 } else {
3707 /* deny the externally proposed config format
3708 * and use the one specified in audio_hw layer configuration.
3709 * Note: out->format is returned by out->stream.common.get_format()
3710 * and is used to set config->format in the code several lines below.
3711 */
3712 out->format = audio_format_from_pcm_format(out->config.format);
3713 }
3714 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003715 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003716 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003717
3718 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3719 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3720 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3721 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3722 __func__, config->sample_rate, config->format, config->channel_mask);
3723 config->sample_rate = out->sample_rate;
3724 config->format = out->format;
3725 config->channel_mask = out->channel_mask;
3726 ret = -EINVAL;
3727 goto error_open;
3728 }
3729
Andy Hung6fcba9c2014-03-18 11:53:32 -07003730 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3731 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003733 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003734 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003735 adev->primary_output = out;
3736 else {
3737 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003738 ret = -EEXIST;
3739 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003740 }
3741 }
3742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743 /* Check if this usecase is already existing */
3744 pthread_mutex_lock(&adev->lock);
3745 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3746 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003747 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003748 ret = -EEXIST;
3749 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 }
3751 pthread_mutex_unlock(&adev->lock);
3752
3753 out->stream.common.get_sample_rate = out_get_sample_rate;
3754 out->stream.common.set_sample_rate = out_set_sample_rate;
3755 out->stream.common.get_buffer_size = out_get_buffer_size;
3756 out->stream.common.get_channels = out_get_channels;
3757 out->stream.common.get_format = out_get_format;
3758 out->stream.common.set_format = out_set_format;
3759 out->stream.common.standby = out_standby;
3760 out->stream.common.dump = out_dump;
3761 out->stream.common.set_parameters = out_set_parameters;
3762 out->stream.common.get_parameters = out_get_parameters;
3763 out->stream.common.add_audio_effect = out_add_audio_effect;
3764 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3765 out->stream.get_latency = out_get_latency;
3766 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003767#ifdef NO_AUDIO_OUT
3768 out->stream.write = out_write_for_no_output;
3769#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003770 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003771#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 out->stream.get_render_position = out_get_render_position;
3773 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003774 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775
Eric Laurent0e46adf2016-12-16 12:49:24 -08003776 if (out->realtime)
3777 out->af_period_multiplier = af_period_multiplier;
3778 else
3779 out->af_period_multiplier = 1;
3780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003781 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003782 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003783 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003785 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003786 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003787 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3788
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003789 config->format = out->stream.common.get_format(&out->stream.common);
3790 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3791 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3792
Andy Hunga452b0a2017-03-15 14:51:15 -07003793 out->error_log = error_log_create(
3794 ERROR_LOG_ENTRIES,
3795 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3796
Andy Hungfc044e12017-03-20 09:24:22 -07003797 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003798 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003799 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003800 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3801 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3802
3803 out->power_log = power_log_create(
3804 config->sample_rate,
3805 audio_channel_count_from_out_mask(config->channel_mask),
3806 config->format,
3807 POWER_LOG_ENTRIES,
3808 POWER_LOG_FRAMES_PER_ENTRY);
3809 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003810
3811 /*
3812 By locking output stream before registering, we allow the callback
3813 to update stream's state only after stream's initial state is set to
3814 adev state.
3815 */
3816 lock_output_stream(out);
3817 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3818 pthread_mutex_lock(&adev->lock);
3819 out->card_status = adev->card_status;
3820 pthread_mutex_unlock(&adev->lock);
3821 pthread_mutex_unlock(&out->lock);
3822
vivek mehta4a824772017-06-08 19:05:49 -07003823 stream_app_type_cfg_init(&out->app_type_cfg);
3824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003826
Eric Laurent994a6932013-07-17 11:51:42 -07003827 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003829
3830error_open:
3831 free(out);
3832 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003833 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003834 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835}
3836
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003837static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 struct audio_stream_out *stream)
3839{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003840 struct stream_out *out = (struct stream_out *)stream;
3841 struct audio_device *adev = out->dev;
3842
Eric Laurent994a6932013-07-17 11:51:42 -07003843 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003844
3845 // must deregister from sndmonitor first to prevent races
3846 // between the callback and close_stream
3847 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003849 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3850 destroy_offload_callback_thread(out);
3851
3852 if (out->compr_config.codec != NULL)
3853 free(out->compr_config.codec);
3854 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003855
3856 if (adev->voice_tx_output == out)
3857 adev->voice_tx_output = NULL;
3858
Andy Hungfc044e12017-03-20 09:24:22 -07003859 power_log_destroy(out->power_log);
3860 out->power_log = NULL;
3861
Andy Hunga452b0a2017-03-15 14:51:15 -07003862 error_log_destroy(out->error_log);
3863 out->error_log = NULL;
3864
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003865 pthread_cond_destroy(&out->cond);
3866 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003867 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003868 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869}
3870
3871static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3872{
3873 struct audio_device *adev = (struct audio_device *)dev;
3874 struct str_parms *parms;
3875 char *str;
3876 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003877 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003878 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003879 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880
Joe Onorato188b6222016-03-01 11:02:27 -08003881 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003882
3883 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003884
3885 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003886 status = voice_set_parameters(adev, parms);
3887 if (status != 0) {
3888 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889 }
3890
3891 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3892 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003893 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3895 adev->bluetooth_nrec = true;
3896 else
3897 adev->bluetooth_nrec = false;
3898 }
3899
3900 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3901 if (ret >= 0) {
3902 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3903 adev->screen_off = false;
3904 else
3905 adev->screen_off = true;
3906 }
3907
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003908 ret = str_parms_get_int(parms, "rotation", &val);
3909 if (ret >= 0) {
3910 bool reverse_speakers = false;
3911 switch(val) {
3912 // FIXME: note that the code below assumes that the speakers are in the correct placement
3913 // relative to the user when the device is rotated 90deg from its default rotation. This
3914 // assumption is device-specific, not platform-specific like this code.
3915 case 270:
3916 reverse_speakers = true;
3917 break;
3918 case 0:
3919 case 90:
3920 case 180:
3921 break;
3922 default:
3923 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003924 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003925 }
Eric Laurent03f09432014-03-25 18:09:11 -07003926 if (status == 0) {
vivek mehtae59cfb22017-06-16 15:57:11 -07003927 // check and set swap
3928 // - check if orientation changed and speaker active
3929 // - set rotation and cache the rotation value
3930 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003931 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003932 }
3933
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003934 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3935 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003936 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003937 }
3938
David Linee3fe402017-03-13 10:00:42 -07003939 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3940 if (ret >= 0) {
3941 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003942 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003943 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3944 if (ret >= 0) {
3945 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003946 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003947 }
Eric Laurent99dab492017-06-17 15:19:08 -07003948 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003949 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3950 if (ret >= 0) {
3951 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003952 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003953 }
3954 }
3955 }
3956
3957 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3958 if (ret >= 0) {
3959 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003960 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003961 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3962 if (ret >= 0) {
3963 const int card = atoi(value);
3964
Eric Laurent99dab492017-06-17 15:19:08 -07003965 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003966 }
Eric Laurent99dab492017-06-17 15:19:08 -07003967 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003968 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3969 if (ret >= 0) {
3970 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003971 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003972 }
3973 }
3974 }
3975
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003976 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003977done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003978 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003979 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003980 ALOGV("%s: exit with code(%d)", __func__, status);
3981 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982}
3983
3984static char* adev_get_parameters(const struct audio_hw_device *dev,
3985 const char *keys)
3986{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003987 struct audio_device *adev = (struct audio_device *)dev;
3988 struct str_parms *reply = str_parms_create();
3989 struct str_parms *query = str_parms_create_str(keys);
3990 char *str;
3991
3992 pthread_mutex_lock(&adev->lock);
3993
3994 voice_get_parameters(adev, query, reply);
3995 str = str_parms_to_str(reply);
3996 str_parms_destroy(query);
3997 str_parms_destroy(reply);
3998
3999 pthread_mutex_unlock(&adev->lock);
4000 ALOGV("%s: exit: returns - %s", __func__, str);
4001 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004002}
4003
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004004static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004005{
4006 return 0;
4007}
4008
Haynes Mathew George5191a852013-09-11 14:19:36 -07004009static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
4010{
4011 int ret;
4012 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004013
Eric Laurent4cc4ce12014-09-10 13:21:01 -05004014 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
4015
Haynes Mathew George5191a852013-09-11 14:19:36 -07004016 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004017 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07004018 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004019
Haynes Mathew George5191a852013-09-11 14:19:36 -07004020 return ret;
4021}
4022
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004023static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024{
4025 return -ENOSYS;
4026}
4027
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004028static int adev_get_master_volume(struct audio_hw_device *dev __unused,
4029 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004030{
4031 return -ENOSYS;
4032}
4033
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004034static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004035{
4036 return -ENOSYS;
4037}
4038
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004039static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004040{
4041 return -ENOSYS;
4042}
4043
4044static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
4045{
4046 struct audio_device *adev = (struct audio_device *)dev;
4047
4048 pthread_mutex_lock(&adev->lock);
4049 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07004050 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07004052 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
4053 voice_is_in_call(adev)) {
4054 voice_stop_call(adev);
4055 adev->current_call_output = NULL;
4056 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004057 }
4058 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004059
4060 audio_extn_extspk_set_mode(adev->extspk, mode);
4061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062 return 0;
4063}
4064
4065static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4066{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004067 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004069
Eric Laurent2bafff12016-03-17 12:17:23 -07004070 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004071 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004072 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4073 ret = audio_extn_hfp_set_mic_mute(adev, state);
4074 } else {
4075 ret = voice_set_mic_mute(adev, state);
4076 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004077 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004078 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004079
4080 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004081}
4082
4083static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4084{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004085 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004086 return 0;
4087}
4088
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004089static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004090 const struct audio_config *config)
4091{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004092 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004093
vivek mehtaa68fea62017-06-08 19:04:02 -07004094 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4095 config->sample_rate, config->format,
4096 channel_count,
4097 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004098}
4099
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004100static bool adev_input_allow_hifi_record(struct audio_device *adev,
4101 audio_devices_t devices,
4102 audio_input_flags_t flags,
4103 audio_source_t source) {
4104 const bool allowed = true;
4105
4106 if (!audio_is_usb_in_device(devices))
4107 return !allowed;
4108
4109 switch (flags) {
4110 case AUDIO_INPUT_FLAG_NONE:
4111 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4112 break;
4113 default:
4114 return !allowed;
4115 }
4116
4117 switch (source) {
4118 case AUDIO_SOURCE_DEFAULT:
4119 case AUDIO_SOURCE_MIC:
4120 case AUDIO_SOURCE_UNPROCESSED:
4121 break;
4122 default:
4123 return !allowed;
4124 }
4125
4126 switch (adev->mode) {
4127 case 0:
4128 break;
4129 default:
4130 return !allowed;
4131 }
4132
4133 return allowed;
4134}
4135
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004137 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004138 audio_devices_t devices,
4139 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004140 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004141 audio_input_flags_t flags,
4142 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004143 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004144{
4145 struct audio_device *adev = (struct audio_device *)dev;
4146 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004147 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004148 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004149 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004150 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004151 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4152 devices,
4153 flags,
4154 source);
4155 ALOGE("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004156 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004157
4158 if (config->sample_rate == 0)
4159 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4160 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4161 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4162 if (config->format == AUDIO_FORMAT_DEFAULT)
4163 config->format = AUDIO_FORMAT_PCM_16_BIT;
4164
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004165 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
4166 return -EINVAL;
4167
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004168 if (audio_extn_tfa_98xx_is_supported() &&
4169 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004170 return -EINVAL;
4171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004172 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4173
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004174 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004175 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177 in->stream.common.get_sample_rate = in_get_sample_rate;
4178 in->stream.common.set_sample_rate = in_set_sample_rate;
4179 in->stream.common.get_buffer_size = in_get_buffer_size;
4180 in->stream.common.get_channels = in_get_channels;
4181 in->stream.common.get_format = in_get_format;
4182 in->stream.common.set_format = in_set_format;
4183 in->stream.common.standby = in_standby;
4184 in->stream.common.dump = in_dump;
4185 in->stream.common.set_parameters = in_set_parameters;
4186 in->stream.common.get_parameters = in_get_parameters;
4187 in->stream.common.add_audio_effect = in_add_audio_effect;
4188 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4189 in->stream.set_gain = in_set_gain;
4190 in->stream.read = in_read;
4191 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004192 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004193
4194 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004195 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197 in->standby = 1;
4198 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004199 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004200 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004201
Haynes Mathew George569b7482017-05-08 14:44:27 -07004202 if (is_usb_dev && may_use_hifi_record) {
4203 /* HiFi record selects an appropriate format, channel, rate combo
4204 depending on sink capabilities*/
4205 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4206 &config->format,
4207 &in->supported_formats[0],
4208 MAX_SUPPORTED_FORMATS,
4209 &config->channel_mask,
4210 &in->supported_channel_masks[0],
4211 MAX_SUPPORTED_CHANNEL_MASKS,
4212 &config->sample_rate,
4213 &in->supported_sample_rates[0],
4214 MAX_SUPPORTED_SAMPLE_RATES);
4215 if (ret != 0) {
4216 ret = -EINVAL;
4217 goto err_open;
4218 }
4219 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004220 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004221 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4222 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4223 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4224 bool ret_error = false;
4225 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4226 from HAL is 8_24
4227 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4228 8_24 return error indicating supported format is 8_24
4229 *> In case of any other source requesting 24 bit or float return error
4230 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004231
vivek mehta57ff9b52016-04-28 14:13:08 -07004232 on error flinger will retry with supported format passed
4233 */
4234 if (source != AUDIO_SOURCE_UNPROCESSED) {
4235 config->format = AUDIO_FORMAT_PCM_16_BIT;
4236 ret_error = true;
4237 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4238 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4239 ret_error = true;
4240 }
4241
4242 if (ret_error) {
4243 ret = -EINVAL;
4244 goto err_open;
4245 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004246 }
4247
vivek mehta57ff9b52016-04-28 14:13:08 -07004248 in->format = config->format;
4249
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004251 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4252 if (config->sample_rate == 0)
4253 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4254 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4255 config->sample_rate != 8000) {
4256 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4257 ret = -EINVAL;
4258 goto err_open;
4259 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004260
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004261 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4262 config->format = AUDIO_FORMAT_PCM_16_BIT;
4263 ret = -EINVAL;
4264 goto err_open;
4265 }
4266
4267 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4268 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004269 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004270 } else if (is_usb_dev && may_use_hifi_record) {
4271 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4272 in->config = pcm_config_audio_capture;
4273 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004274 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4275 config->sample_rate,
4276 config->format,
4277 channel_count,
4278 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004279 in->config.period_size = buffer_size / frame_size;
4280 in->config.rate = config->sample_rate;
4281 in->af_period_multiplier = 1;
4282 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004283 } else {
4284 in->usecase = USECASE_AUDIO_RECORD;
4285 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004286 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004287 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004288#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004289 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004290#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004291 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004292 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004293 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004294 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004295 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4296 config->sample_rate,
4297 config->format,
4298 channel_count,
4299 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004300 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004301 in->config.rate = config->sample_rate;
4302 in->af_period_multiplier = 1;
4303 } else {
4304 // period size is left untouched for rt mode playback
4305 in->config = pcm_config_audio_capture_rt;
4306 in->af_period_multiplier = af_period_multiplier;
4307 }
4308 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4309 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004310 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004311 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4312 in->config = pcm_config_mmap_capture;
4313 in->stream.start = in_start;
4314 in->stream.stop = in_stop;
4315 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4316 in->stream.get_mmap_position = in_get_mmap_position;
4317 in->af_period_multiplier = 1;
4318 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004319 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
4320 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004321 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004322 (config->sample_rate == 8000 ||
4323 config->sample_rate == 16000 ||
4324 config->sample_rate == 32000 ||
4325 config->sample_rate == 48000) &&
4326 channel_count == 1) {
4327 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4328 in->config = pcm_config_audio_capture;
4329 frame_size = audio_stream_in_frame_size(&in->stream);
4330 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4331 config->sample_rate,
4332 config->format,
4333 channel_count, false /*is_low_latency*/);
4334 in->config.period_size = buffer_size / frame_size;
4335 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4336 in->config.rate = config->sample_rate;
4337 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004338 } else {
4339 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004340 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004341 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4342 config->sample_rate,
4343 config->format,
4344 channel_count,
4345 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004346 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004347 in->config.rate = config->sample_rate;
4348 in->af_period_multiplier = 1;
4349 }
4350 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4351 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004352 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004354 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004355 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004356
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004357 /* This stream could be for sound trigger lab,
4358 get sound trigger pcm if present */
4359 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004360
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004361 lock_input_stream(in);
4362 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4363 pthread_mutex_lock(&adev->lock);
4364 in->card_status = adev->card_status;
4365 pthread_mutex_unlock(&adev->lock);
4366 pthread_mutex_unlock(&in->lock);
4367
vivek mehta4a824772017-06-08 19:05:49 -07004368 stream_app_type_cfg_init(&in->app_type_cfg);
4369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004371 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004372 return 0;
4373
4374err_open:
4375 free(in);
4376 *stream_in = NULL;
4377 return ret;
4378}
4379
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004380static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381 struct audio_stream_in *stream)
4382{
Eric Laurent994a6932013-07-17 11:51:42 -07004383 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004384
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004385 // must deregister from sndmonitor first to prevent races
4386 // between the callback and close_stream
4387 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004388 in_standby(&stream->common);
4389 free(stream);
4390
4391 return;
4392}
4393
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004394static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004395{
4396 return 0;
4397}
4398
Andy Hung31aca912014-03-20 17:14:59 -07004399/* verifies input and output devices and their capabilities.
4400 *
4401 * This verification is required when enabling extended bit-depth or
4402 * sampling rates, as not all qcom products support it.
4403 *
4404 * Suitable for calling only on initialization such as adev_open().
4405 * It fills the audio_device use_case_table[] array.
4406 *
4407 * Has a side-effect that it needs to configure audio routing / devices
4408 * in order to power up the devices and read the device parameters.
4409 * It does not acquire any hw device lock. Should restore the devices
4410 * back to "normal state" upon completion.
4411 */
4412static int adev_verify_devices(struct audio_device *adev)
4413{
4414 /* enumeration is a bit difficult because one really wants to pull
4415 * the use_case, device id, etc from the hidden pcm_device_table[].
4416 * In this case there are the following use cases and device ids.
4417 *
4418 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4419 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004420 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004421 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4422 * [USECASE_AUDIO_RECORD] = {0, 0},
4423 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4424 * [USECASE_VOICE_CALL] = {2, 2},
4425 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004426 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004427 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4428 */
4429
4430 /* should be the usecases enabled in adev_open_input_stream() */
4431 static const int test_in_usecases[] = {
4432 USECASE_AUDIO_RECORD,
4433 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4434 };
4435 /* should be the usecases enabled in adev_open_output_stream()*/
4436 static const int test_out_usecases[] = {
4437 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4438 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4439 };
4440 static const usecase_type_t usecase_type_by_dir[] = {
4441 PCM_PLAYBACK,
4442 PCM_CAPTURE,
4443 };
4444 static const unsigned flags_by_dir[] = {
4445 PCM_OUT,
4446 PCM_IN,
4447 };
4448
4449 size_t i;
4450 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004451 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004452 char info[512]; /* for possible debug info */
4453
4454 for (dir = 0; dir < 2; ++dir) {
4455 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4456 const unsigned flags_dir = flags_by_dir[dir];
4457 const size_t testsize =
4458 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4459 const int *testcases =
4460 dir ? test_in_usecases : test_out_usecases;
4461 const audio_devices_t audio_device =
4462 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4463
4464 for (i = 0; i < testsize; ++i) {
4465 const audio_usecase_t audio_usecase = testcases[i];
4466 int device_id;
4467 snd_device_t snd_device;
4468 struct pcm_params **pparams;
4469 struct stream_out out;
4470 struct stream_in in;
4471 struct audio_usecase uc_info;
4472 int retval;
4473
4474 pparams = &adev->use_case_table[audio_usecase];
4475 pcm_params_free(*pparams); /* can accept null input */
4476 *pparams = NULL;
4477
4478 /* find the device ID for the use case (signed, for error) */
4479 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4480 if (device_id < 0)
4481 continue;
4482
4483 /* prepare structures for device probing */
4484 memset(&uc_info, 0, sizeof(uc_info));
4485 uc_info.id = audio_usecase;
4486 uc_info.type = usecase_type;
4487 if (dir) {
4488 adev->active_input = &in;
4489 memset(&in, 0, sizeof(in));
4490 in.device = audio_device;
4491 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4492 uc_info.stream.in = &in;
4493 } else {
4494 adev->active_input = NULL;
4495 }
4496 memset(&out, 0, sizeof(out));
4497 out.devices = audio_device; /* only field needed in select_devices */
4498 uc_info.stream.out = &out;
4499 uc_info.devices = audio_device;
4500 uc_info.in_snd_device = SND_DEVICE_NONE;
4501 uc_info.out_snd_device = SND_DEVICE_NONE;
4502 list_add_tail(&adev->usecase_list, &uc_info.list);
4503
4504 /* select device - similar to start_(in/out)put_stream() */
4505 retval = select_devices(adev, audio_usecase);
4506 if (retval >= 0) {
4507 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4508#if LOG_NDEBUG == 0
4509 if (*pparams) {
4510 ALOGV("%s: (%s) card %d device %d", __func__,
4511 dir ? "input" : "output", card_id, device_id);
4512 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004513 } else {
4514 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4515 }
4516#endif
4517 }
4518
4519 /* deselect device - similar to stop_(in/out)put_stream() */
4520 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004521 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004522 /* 2. Disable the rx device */
4523 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004524 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004525 list_remove(&uc_info.list);
4526 }
4527 }
4528 adev->active_input = NULL; /* restore adev state */
4529 return 0;
4530}
4531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532static int adev_close(hw_device_t *device)
4533{
Andy Hung31aca912014-03-20 17:14:59 -07004534 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004536
4537 if (!adev)
4538 return 0;
4539
4540 pthread_mutex_lock(&adev_init_lock);
4541
4542 if ((--audio_device_ref_count) == 0) {
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004543 audio_extn_snd_mon_unregister_listener(adev);
4544 audio_extn_tfa_98xx_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004545 audio_route_free(adev->audio_route);
4546 free(adev->snd_dev_ref_cnt);
4547 platform_deinit(adev->platform);
4548 audio_extn_extspk_deinit(adev->extspk);
4549 audio_extn_sound_trigger_deinit(adev);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004550 audio_extn_snd_mon_deinit();
vivek mehta1a9b7c02015-06-25 11:49:38 -07004551 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4552 pcm_params_free(adev->use_case_table[i]);
4553 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004554 if (adev->adm_deinit)
4555 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004556 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004557 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004558
4559 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004561 return 0;
4562}
4563
Glenn Kasten4f993392014-05-14 07:30:48 -07004564/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4565 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4566 * just that it _might_ work.
4567 */
4568static int period_size_is_plausible_for_low_latency(int period_size)
4569{
4570 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004571 case 48:
4572 case 96:
4573 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004574 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004575 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004576 case 240:
4577 case 320:
4578 case 480:
4579 return 1;
4580 default:
4581 return 0;
4582 }
4583}
4584
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004585static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4586{
4587 int card;
4588 card_status_t status;
4589
4590 if (!parms)
4591 return;
4592
4593 if (parse_snd_card_status(parms, &card, &status) < 0)
4594 return;
4595
4596 pthread_mutex_lock(&adev->lock);
4597 bool valid_cb = (card == adev->snd_card);
4598 if (valid_cb) {
4599 if (adev->card_status != status) {
4600 adev->card_status = status;
4601 platform_snd_card_update(adev->platform, status);
4602 }
4603 }
4604 pthread_mutex_unlock(&adev->lock);
4605 return;
4606}
4607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004608static int adev_open(const hw_module_t *module, const char *name,
4609 hw_device_t **device)
4610{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004611 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004612
Eric Laurent2bafff12016-03-17 12:17:23 -07004613 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004614 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004615 pthread_mutex_lock(&adev_init_lock);
4616 if (audio_device_ref_count != 0) {
4617 *device = &adev->device.common;
4618 audio_device_ref_count++;
4619 ALOGV("%s: returning existing instance of adev", __func__);
4620 ALOGV("%s: exit", __func__);
4621 pthread_mutex_unlock(&adev_init_lock);
4622 return 0;
4623 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004624 adev = calloc(1, sizeof(struct audio_device));
4625
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004626 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4627
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004628 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4629 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4630 adev->device.common.module = (struct hw_module_t *)module;
4631 adev->device.common.close = adev_close;
4632
4633 adev->device.init_check = adev_init_check;
4634 adev->device.set_voice_volume = adev_set_voice_volume;
4635 adev->device.set_master_volume = adev_set_master_volume;
4636 adev->device.get_master_volume = adev_get_master_volume;
4637 adev->device.set_master_mute = adev_set_master_mute;
4638 adev->device.get_master_mute = adev_get_master_mute;
4639 adev->device.set_mode = adev_set_mode;
4640 adev->device.set_mic_mute = adev_set_mic_mute;
4641 adev->device.get_mic_mute = adev_get_mic_mute;
4642 adev->device.set_parameters = adev_set_parameters;
4643 adev->device.get_parameters = adev_get_parameters;
4644 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4645 adev->device.open_output_stream = adev_open_output_stream;
4646 adev->device.close_output_stream = adev_close_output_stream;
4647 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649 adev->device.close_input_stream = adev_close_input_stream;
4650 adev->device.dump = adev_dump;
4651
4652 /* Set the default route before the PCM stream is opened */
4653 pthread_mutex_lock(&adev->lock);
4654 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004655 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004656 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004657 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004658 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004659 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004660 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004661 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004662 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004663 pthread_mutex_unlock(&adev->lock);
4664
4665 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004666 adev->platform = platform_init(adev);
4667 if (!adev->platform) {
4668 free(adev->snd_dev_ref_cnt);
4669 free(adev);
4670 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4671 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004672 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004673 return -EINVAL;
4674 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004675 adev->extspk = audio_extn_extspk_init(adev);
4676
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004677 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4678 if (adev->visualizer_lib == NULL) {
4679 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4680 } else {
4681 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4682 adev->visualizer_start_output =
4683 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4684 "visualizer_hal_start_output");
4685 adev->visualizer_stop_output =
4686 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4687 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004688 }
4689
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004690 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4691 if (adev->offload_effects_lib == NULL) {
4692 ALOGW("%s: DLOPEN failed for %s", __func__,
4693 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4694 } else {
4695 ALOGV("%s: DLOPEN successful for %s", __func__,
4696 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4697 adev->offload_effects_start_output =
4698 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4699 "offload_effects_bundle_hal_start_output");
4700 adev->offload_effects_stop_output =
4701 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4702 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004703 }
4704
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004705 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4706 if (adev->adm_lib == NULL) {
4707 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4708 } else {
4709 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4710 adev->adm_init = (adm_init_t)
4711 dlsym(adev->adm_lib, "adm_init");
4712 adev->adm_deinit = (adm_deinit_t)
4713 dlsym(adev->adm_lib, "adm_deinit");
4714 adev->adm_register_input_stream = (adm_register_input_stream_t)
4715 dlsym(adev->adm_lib, "adm_register_input_stream");
4716 adev->adm_register_output_stream = (adm_register_output_stream_t)
4717 dlsym(adev->adm_lib, "adm_register_output_stream");
4718 adev->adm_deregister_stream = (adm_deregister_stream_t)
4719 dlsym(adev->adm_lib, "adm_deregister_stream");
4720 adev->adm_request_focus = (adm_request_focus_t)
4721 dlsym(adev->adm_lib, "adm_request_focus");
4722 adev->adm_abandon_focus = (adm_abandon_focus_t)
4723 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004724 adev->adm_set_config = (adm_set_config_t)
4725 dlsym(adev->adm_lib, "adm_set_config");
4726 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4727 dlsym(adev->adm_lib, "adm_request_focus_v2");
4728 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4729 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4730 adev->adm_on_routing_change = (adm_on_routing_change_t)
4731 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004732 }
4733
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004734 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004735 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004736
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004737 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004738
Andy Hung31aca912014-03-20 17:14:59 -07004739 if (k_enable_extended_precision)
4740 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004741
Glenn Kasten4f993392014-05-14 07:30:48 -07004742 char value[PROPERTY_VALUE_MAX];
4743 int trial;
4744 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4745 trial = atoi(value);
4746 if (period_size_is_plausible_for_low_latency(trial)) {
4747 pcm_config_low_latency.period_size = trial;
4748 pcm_config_low_latency.start_threshold = trial / 4;
4749 pcm_config_low_latency.avail_min = trial / 4;
4750 configured_low_latency_capture_period_size = trial;
4751 }
4752 }
4753 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4754 trial = atoi(value);
4755 if (period_size_is_plausible_for_low_latency(trial)) {
4756 configured_low_latency_capture_period_size = trial;
4757 }
4758 }
4759
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004760 // commented as full set of app type cfg is sent from platform
4761 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004762 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004763
4764 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4765 af_period_multiplier = atoi(value);
4766 if (af_period_multiplier < 0) {
4767 af_period_multiplier = 2;
4768 } else if (af_period_multiplier > 4) {
4769 af_period_multiplier = 4;
4770 }
4771 ALOGV("new period_multiplier = %d", af_period_multiplier);
4772 }
4773
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004774 audio_extn_tfa_98xx_init(adev);
4775
vivek mehta1a9b7c02015-06-25 11:49:38 -07004776 pthread_mutex_unlock(&adev_init_lock);
4777
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004778 if (adev->adm_init)
4779 adev->adm_data = adev->adm_init();
4780
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004781 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004782 audio_extn_snd_mon_init();
4783 pthread_mutex_lock(&adev->lock);
4784 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4785 adev->card_status = CARD_STATUS_ONLINE;
4786 pthread_mutex_unlock(&adev->lock);
Haynes Mathew Georgeceafc552017-05-24 15:44:23 -07004787 audio_extn_sound_trigger_init(adev);/* dependent on snd_mon_init() */
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004788
Eric Laurent2bafff12016-03-17 12:17:23 -07004789 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790 return 0;
4791}
4792
4793static struct hw_module_methods_t hal_module_methods = {
4794 .open = adev_open,
4795};
4796
4797struct audio_module HAL_MODULE_INFO_SYM = {
4798 .common = {
4799 .tag = HARDWARE_MODULE_TAG,
4800 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4801 .hal_api_version = HARDWARE_HAL_API_VERSION,
4802 .id = AUDIO_HARDWARE_MODULE_ID,
4803 .name = "QCOM Audio HAL",
4804 .author = "Code Aurora Forum",
4805 .methods = &hal_module_methods,
4806 },
4807};