blob: e5a885479eaf26f5e249d1f97638edc823aa927d [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 ||
683 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
684 audio_extn_spkr_prot_is_enabled()) {
685 audio_extn_spkr_prot_stop_processing(snd_device);
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700686 } else if (platform_can_split_snd_device(snd_device,
687 &num_devices,
688 new_snd_devices) == 0) {
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700689 for (i = 0; i < num_devices; i++) {
690 disable_snd_device(adev, new_snd_devices[i]);
691 }
vivek mehtab6506412015-08-07 16:55:17 -0700692 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700693 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800694 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
695 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
696 ALOGE(" %s: Invalid sound device returned", __func__);
697 return -EINVAL;
698 }
699
Eric Laurent2e140aa2016-06-30 17:14:46 -0700700 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
vivek mehtade4849c2016-03-03 17:23:38 -0800701 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700702 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700703 audio_extn_sound_trigger_update_device_status(snd_device,
704 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700705 }
vivek mehtab6506412015-08-07 16:55:17 -0700706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800707 return 0;
708}
709
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700710/*
711 legend:
712 uc - existing usecase
713 new_uc - new usecase
714 d1, d11, d2 - SND_DEVICE enums
715 a1, a2 - corresponding ANDROID device enums
716 B, B1, B2 - backend strings
717
718case 1
719 uc->dev d1 (a1) B1
720 new_uc->dev d1 (a1), d2 (a2) B1, B2
721
722 resolution: disable and enable uc->dev on d1
723
724case 2
725 uc->dev d1 (a1) B1
726 new_uc->dev d11 (a1) B1
727
728 resolution: need to switch uc since d1 and d11 are related
729 (e.g. speaker and voice-speaker)
730 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
731
732case 3
733 uc->dev d1 (a1) B1
734 new_uc->dev d2 (a2) B2
735
736 resolution: no need to switch uc
737
738case 4
739 uc->dev d1 (a1) B
740 new_uc->dev d2 (a2) B
741
742 resolution: disable enable uc-dev on d2 since backends match
743 we cannot enable two streams on two different devices if they
744 share the same backend. e.g. if offload is on speaker device using
745 QUAD_MI2S backend and a low-latency stream is started on voice-handset
746 using the same backend, offload must also be switched to voice-handset.
747
748case 5
749 uc->dev d1 (a1) B
750 new_uc->dev d1 (a1), d2 (a2) B
751
752 resolution: disable enable uc-dev on d2 since backends match
753 we cannot enable two streams on two different devices if they
754 share the same backend.
755
756case 6
757 uc->dev d1 a1 B1
758 new_uc->dev d2 a1 B2
759
760 resolution: no need to switch
761
762case 7
763
764 uc->dev d1 (a1), d2 (a2) B1, B2
765 new_uc->dev d1 B1
766
767 resolution: no need to switch
768
769*/
770static snd_device_t derive_playback_snd_device(struct audio_usecase *uc,
771 struct audio_usecase *new_uc,
772 snd_device_t new_snd_device)
773{
774 audio_devices_t a1 = uc->stream.out->devices;
775 audio_devices_t a2 = new_uc->stream.out->devices;
776
777 snd_device_t d1 = uc->out_snd_device;
778 snd_device_t d2 = new_snd_device;
779
780 // Treat as a special case when a1 and a2 are not disjoint
781 if ((a1 != a2) && (a1 & a2)) {
782 snd_device_t d3[2];
783 int num_devices = 0;
784 int ret = platform_can_split_snd_device(popcount(a1) > 1 ? d1 : d2,
785 &num_devices,
786 d3);
787 if (ret < 0) {
788 if (ret != -ENOSYS) {
789 ALOGW("%s failed to split snd_device %d",
790 __func__,
791 popcount(a1) > 1 ? d1 : d2);
792 }
793 goto end;
794 }
795
796 // NB: case 7 is hypothetical and isn't a practical usecase yet.
797 // But if it does happen, we need to give priority to d2 if
798 // the combo devices active on the existing usecase share a backend.
799 // This is because we cannot have a usecase active on a combo device
800 // and a new usecase requests one device in this combo pair.
801 if (platform_check_backends_match(d3[0], d3[1])) {
802 return d2; // case 5
803 } else {
804 return d1; // case 1
805 }
806 } else {
807 if (platform_check_backends_match(d1, d2)) {
808 return d2; // case 2, 4
809 } else {
810 return d1; // case 6, 3
811 }
812 }
813
814end:
815 return d2; // return whatever was calculated before.
816}
817
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700818static void check_and_route_playback_usecases(struct audio_device *adev,
819 struct audio_usecase *uc_info,
820 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700821{
822 struct listnode *node;
823 struct audio_usecase *usecase;
824 bool switch_device[AUDIO_USECASE_MAX];
825 int i, num_uc_to_switch = 0;
826
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700827 bool force_routing = platform_check_and_set_playback_backend_cfg(adev,
828 uc_info,
829 snd_device);
David Linee3fe402017-03-13 10:00:42 -0700830
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831 /*
832 * This function is to make sure that all the usecases that are active on
833 * the hardware codec backend are always routed to any one device that is
834 * handled by the hardware codec.
835 * For example, if low-latency and deep-buffer usecases are currently active
836 * on speaker and out_set_parameters(headset) is received on low-latency
837 * output, then we have to make sure deep-buffer is also switched to headset,
838 * because of the limitation that both the devices cannot be enabled
839 * at the same time as they share the same backend.
840 */
841 /* Disable all the usecases on the shared backend other than the
842 specified usecase */
843 for (i = 0; i < AUDIO_USECASE_MAX; i++)
844 switch_device[i] = false;
845
846 list_for_each(node, &adev->usecase_list) {
847 usecase = node_to_item(node, struct audio_usecase, list);
Haynes Mathew George137a2ee2017-05-23 17:03:35 -0700848 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
849 continue;
850
851 if (force_routing ||
852 (usecase->out_snd_device != snd_device &&
853 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
854 platform_check_backends_match(snd_device, usecase->out_snd_device))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
856 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700857 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700858 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700859 switch_device[usecase->id] = true;
860 num_uc_to_switch++;
861 }
862 }
863
864 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 list_for_each(node, &adev->usecase_list) {
866 usecase = node_to_item(node, struct audio_usecase, list);
867 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700868 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900869 }
870 }
871
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700872 snd_device_t d_device;
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900873 list_for_each(node, &adev->usecase_list) {
874 usecase = node_to_item(node, struct audio_usecase, list);
875 if (switch_device[usecase->id]) {
Haynes Mathew George2d809e02016-09-22 17:38:16 -0700876 d_device = derive_playback_snd_device(usecase, uc_info,
877 snd_device);
878 enable_snd_device(adev, d_device);
879 /* Update the out_snd_device before enabling the audio route */
880 usecase->out_snd_device = d_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 }
882 }
883
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 /* Re-route all the usecases on the shared backend other than the
885 specified usecase to new snd devices */
886 list_for_each(node, &adev->usecase_list) {
887 usecase = node_to_item(node, struct audio_usecase, list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700888 if (switch_device[usecase->id] ) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700889 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700890 }
891 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700892 }
893}
894
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700895static void check_and_route_capture_usecases(struct audio_device *adev,
896 struct audio_usecase *uc_info,
897 snd_device_t snd_device)
898{
899 struct listnode *node;
900 struct audio_usecase *usecase;
901 bool switch_device[AUDIO_USECASE_MAX];
902 int i, num_uc_to_switch = 0;
903
vivek mehta4ed66e62016-04-15 23:33:34 -0700904 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
905
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700906 /*
907 * This function is to make sure that all the active capture usecases
908 * are always routed to the same input sound device.
909 * For example, if audio-record and voice-call usecases are currently
910 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
911 * is received for voice call then we have to make sure that audio-record
912 * usecase is also switched to earpiece i.e. voice-dmic-ef,
913 * because of the limitation that two devices cannot be enabled
914 * at the same time if they share the same backend.
915 */
916 for (i = 0; i < AUDIO_USECASE_MAX; i++)
917 switch_device[i] = false;
918
919 list_for_each(node, &adev->usecase_list) {
920 usecase = node_to_item(node, struct audio_usecase, list);
921 if (usecase->type != PCM_PLAYBACK &&
922 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700923 usecase->in_snd_device != snd_device &&
924 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700925 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
926 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700927 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700928 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700929 switch_device[usecase->id] = true;
930 num_uc_to_switch++;
931 }
932 }
933
934 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700935 list_for_each(node, &adev->usecase_list) {
936 usecase = node_to_item(node, struct audio_usecase, list);
937 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700938 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700939 }
940 }
941
942 list_for_each(node, &adev->usecase_list) {
943 usecase = node_to_item(node, struct audio_usecase, list);
944 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700945 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700946 }
947 }
948
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700949 /* Re-route all the usecases on the shared backend other than the
950 specified usecase to new snd devices */
951 list_for_each(node, &adev->usecase_list) {
952 usecase = node_to_item(node, struct audio_usecase, list);
953 /* Update the in_snd_device only before enabling the audio route */
954 if (switch_device[usecase->id] ) {
955 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700956 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700957 }
958 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700959 }
960}
961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800962/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700963static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800964{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700965 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700966 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800967
968 switch (channels) {
969 /*
970 * Do not handle stereo output in Multi-channel cases
971 * Stereo case is handled in normal playback path
972 */
973 case 6:
974 ALOGV("%s: HDMI supports 5.1", __func__);
975 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
976 break;
977 case 8:
978 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
979 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
980 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
981 break;
982 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700983 ALOGE("HDMI does not support multi channel playback");
984 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985 break;
986 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700987 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800988}
989
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -0700990static ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
991 uint32_t *supported_sample_rates __unused,
992 uint32_t max_rates __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800993{
Haynes Mathew George569b7482017-05-08 14:44:27 -0700994 ssize_t count = audio_extn_usb_sup_sample_rates(is_playback,
995 supported_sample_rates,
996 max_rates);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -0800997#if !LOG_NDEBUG
Haynes Mathew George569b7482017-05-08 14:44:27 -0700998 for (ssize_t i=0; i<count; i++) {
999 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1000 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001001 }
1002#endif
Haynes Mathew George569b7482017-05-08 14:44:27 -07001003 return count;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001004}
1005
Haynes Mathew George569b7482017-05-08 14:44:27 -07001006static int read_usb_sup_channel_masks(bool is_playback,
1007 audio_channel_mask_t *supported_channel_masks,
1008 uint32_t max_masks __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001009{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001010 int channels = audio_extn_usb_get_max_channels(is_playback);
1011 if (is_playback) {
1012 supported_channel_masks[0] =
1013 channels < 3 ? audio_channel_out_mask_from_count(channels) :
1014 audio_channel_mask_for_index_assignment_from_count(channels);
1015 } else {
1016 supported_channel_masks[0] = audio_channel_in_mask_from_count(channels);
1017 }
1018 ALOGV("%s: %s supported ch %d", __func__,
1019 is_playback ? "P" : "C", channels);
1020 return 1;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001021}
1022
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001023static int read_usb_sup_formats(bool is_playback __unused,
Haynes Mathew George569b7482017-05-08 14:44:27 -07001024 audio_format_t *supported_formats,
1025 uint32_t max_formats __unused)
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001026{
Haynes Mathew George569b7482017-05-08 14:44:27 -07001027 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001028 switch (bitwidth) {
1029 case 24:
1030 // XXX : usb.c returns 24 for s24 and s24_le?
Haynes Mathew George569b7482017-05-08 14:44:27 -07001031 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001032 break;
1033 case 32:
Haynes Mathew George569b7482017-05-08 14:44:27 -07001034 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001035 break;
1036 case 16:
1037 default :
Haynes Mathew George569b7482017-05-08 14:44:27 -07001038 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001039 break;
1040 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07001041 ALOGV("%s: %s supported format %d", __func__,
1042 is_playback ? "P" : "C", bitwidth);
1043 return 1;
1044}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001045
Haynes Mathew George569b7482017-05-08 14:44:27 -07001046static int read_usb_sup_params_and_compare(bool is_playback,
1047 audio_format_t *format,
1048 audio_format_t *supported_formats,
1049 uint32_t max_formats,
1050 audio_channel_mask_t *mask,
1051 audio_channel_mask_t *supported_channel_masks,
1052 uint32_t max_masks,
1053 uint32_t *rate,
1054 uint32_t *supported_sample_rates,
1055 uint32_t max_rates) {
1056 int ret = 0;
1057 int num_formats;
1058 int num_masks;
1059 int num_rates;
1060 int i;
1061
1062 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1063 max_formats);
1064 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1065 max_masks);
1066 num_rates = read_usb_sup_sample_rates(is_playback,
1067 supported_sample_rates, max_rates);
1068
1069#define LUT(table, len, what, dflt) \
1070 for (i=0; i<len && (table[i] != what); i++); \
1071 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1072
1073 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1074 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1075 LUT(supported_sample_rates, num_rates, *rate, 0);
1076
1077#undef LUT
1078 return ret < 0 ? -EINVAL : 0; // HACK TBD
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001079}
1080
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001081static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
1082{
1083 struct audio_usecase *usecase;
1084 struct listnode *node;
1085
1086 list_for_each(node, &adev->usecase_list) {
1087 usecase = node_to_item(node, struct audio_usecase, list);
1088 if (usecase->type == VOICE_CALL) {
1089 ALOGV("%s: usecase id %d", __func__, usecase->id);
1090 return usecase->id;
1091 }
1092 }
1093 return USECASE_INVALID;
1094}
1095
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001096struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
1097 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098{
1099 struct audio_usecase *usecase;
1100 struct listnode *node;
1101
1102 list_for_each(node, &adev->usecase_list) {
1103 usecase = node_to_item(node, struct audio_usecase, list);
1104 if (usecase->id == uc_id)
1105 return usecase;
1106 }
1107 return NULL;
1108}
1109
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001110int select_devices(struct audio_device *adev,
1111 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001113 snd_device_t out_snd_device = SND_DEVICE_NONE;
1114 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001115 struct audio_usecase *usecase = NULL;
1116 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001117 struct audio_usecase *hfp_usecase = NULL;
1118 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001119 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001120 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001122 usecase = get_usecase_from_list(adev, uc_id);
1123 if (usecase == NULL) {
1124 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
1125 return -EINVAL;
1126 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001128 if ((usecase->type == VOICE_CALL) ||
1129 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001130 out_snd_device = platform_get_output_snd_device(adev->platform,
1131 usecase->stream.out->devices);
1132 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 usecase->devices = usecase->stream.out->devices;
1134 } else {
1135 /*
1136 * If the voice call is active, use the sound devices of voice call usecase
1137 * so that it would not result any device switch. All the usecases will
1138 * be switched to new device when select_devices() is called for voice call
1139 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001140 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001141 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001142 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -07001143 vc_usecase = get_usecase_from_list(adev,
1144 get_voice_usecase_id_from_list(adev));
1145 if ((vc_usecase != NULL) &&
1146 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1147 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001148 in_snd_device = vc_usecase->in_snd_device;
1149 out_snd_device = vc_usecase->out_snd_device;
1150 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08001151 } else if (audio_extn_hfp_is_active(adev)) {
1152 hfp_ucid = audio_extn_hfp_get_usecase();
1153 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
1154 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
1155 in_snd_device = hfp_usecase->in_snd_device;
1156 out_snd_device = hfp_usecase->out_snd_device;
1157 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001158 }
1159 if (usecase->type == PCM_PLAYBACK) {
1160 usecase->devices = usecase->stream.out->devices;
1161 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001162 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001163 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001164 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001165 if (usecase->stream.out == adev->primary_output &&
1166 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -07001167 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1168 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001169 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001170 select_devices(adev, adev->active_input->usecase);
1171 }
1172 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 } else if (usecase->type == PCM_CAPTURE) {
1174 usecase->devices = usecase->stream.in->device;
1175 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001176 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001177 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -07001178 if (adev->active_input &&
1179 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
1180 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -08001181 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -07001182 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
1183 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
1184 } else if (adev->primary_output) {
1185 out_device = adev->primary_output->devices;
1186 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001187 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001188 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001189 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001190 }
1191 }
1192
1193 if (out_snd_device == usecase->out_snd_device &&
1194 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001195 return 0;
1196 }
1197
Eric Laurent2bafff12016-03-17 12:17:23 -07001198 if (out_snd_device != SND_DEVICE_NONE &&
1199 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
1200 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1201 __func__,
1202 use_case_table[uc_id],
1203 adev->last_logged_snd_device[uc_id][0],
1204 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
1205 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
1206 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
1207 -1,
1208 out_snd_device,
1209 platform_get_snd_device_name(out_snd_device),
1210 platform_get_snd_device_acdb_id(out_snd_device));
1211 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
1212 }
1213 if (in_snd_device != SND_DEVICE_NONE &&
1214 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
1215 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
1216 __func__,
1217 use_case_table[uc_id],
1218 adev->last_logged_snd_device[uc_id][1],
1219 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
1220 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
1221 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
1222 -1,
1223 in_snd_device,
1224 platform_get_snd_device_name(in_snd_device),
1225 platform_get_snd_device_acdb_id(in_snd_device));
1226 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
1227 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001229 /*
1230 * Limitation: While in call, to do a device switch we need to disable
1231 * and enable both RX and TX devices though one of them is same as current
1232 * device.
1233 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001234 if ((usecase->type == VOICE_CALL) &&
1235 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1236 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001237 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -07001238 /* Disable sidetone only if voice call already exists */
1239 if (voice_is_call_state_active(adev))
1240 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001241 }
1242
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001243 /* Disable current sound devices */
1244 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001245 disable_audio_route(adev, usecase);
1246 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001247 }
1248
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001249 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001250 disable_audio_route(adev, usecase);
1251 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001252 }
1253
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001254 /* Applicable only on the targets that has external modem.
1255 * New device information should be sent to modem before enabling
1256 * the devices to reduce in-call device switch time.
1257 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001258 if ((usecase->type == VOICE_CALL) &&
1259 (usecase->in_snd_device != SND_DEVICE_NONE) &&
1260 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001261 status = platform_switch_voice_call_enable_device_config(adev->platform,
1262 out_snd_device,
1263 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07001264 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001265
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001266 /* Enable new sound devices */
1267 if (out_snd_device != SND_DEVICE_NONE) {
David Linee3fe402017-03-13 10:00:42 -07001268 if ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
Eric Laurent99dab492017-06-17 15:19:08 -07001269 (usecase->devices & (AUDIO_DEVICE_OUT_USB_DEVICE|AUDIO_DEVICE_OUT_USB_HEADSET)))
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001270 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001271 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272 }
1273
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001274 if (in_snd_device != SND_DEVICE_NONE) {
1275 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001276 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001277 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001278
Eric Laurentb23d5282013-05-14 15:27:20 -07001279 if (usecase->type == VOICE_CALL)
1280 status = platform_switch_voice_call_device_post(adev->platform,
1281 out_snd_device,
1282 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001283
sangwoo170731f2013-06-08 15:36:36 +09001284 usecase->in_snd_device = in_snd_device;
1285 usecase->out_snd_device = out_snd_device;
1286
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001287 audio_extn_tfa_98xx_set_mode();
1288
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001289 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001290
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001291 /* Applicable only on the targets that has external modem.
1292 * Enable device command should be sent to modem only after
1293 * enabling voice call mixer controls
1294 */
vivek mehta765eb642015-08-07 19:46:06 -07001295 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001296 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1297 out_snd_device,
1298 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -07001299 /* Enable sidetone only if voice call already exists */
1300 if (voice_is_call_state_active(adev))
1301 voice_set_sidetone(adev, out_snd_device, true);
1302 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -07001303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001304 return status;
1305}
1306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001307static int stop_input_stream(struct stream_in *in)
1308{
1309 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 struct audio_usecase *uc_info;
1311 struct audio_device *adev = in->dev;
1312
Eric Laurentc8400632013-02-14 19:04:54 -08001313 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314
Eric Laurent994a6932013-07-17 11:51:42 -07001315 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001317 uc_info = get_usecase_from_list(adev, in->usecase);
1318 if (uc_info == NULL) {
1319 ALOGE("%s: Could not find the usecase (%d) in the list",
1320 __func__, in->usecase);
1321 return -EINVAL;
1322 }
1323
vivek mehta781065c2017-04-04 12:55:01 -07001324 /* Close in-call recording streams */
1325 voice_check_and_stop_incall_rec_usecase(adev, in);
1326
Eric Laurent150dbfe2013-02-27 14:31:02 -08001327 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001328 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001329
1330 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001331 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001332
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001333 list_remove(&uc_info->list);
1334 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001335
Eric Laurent994a6932013-07-17 11:51:42 -07001336 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001337 return ret;
1338}
1339
1340int start_input_stream(struct stream_in *in)
1341{
1342 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001343 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 struct audio_usecase *uc_info;
1345 struct audio_device *adev = in->dev;
1346
Eric Laurent994a6932013-07-17 11:51:42 -07001347 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001348
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001349 if (audio_extn_tfa_98xx_is_supported() && !audio_ssr_status(adev))
1350 return -EIO;
1351
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001352 if (in->card_status == CARD_STATUS_OFFLINE ||
1353 adev->card_status == CARD_STATUS_OFFLINE) {
1354 ALOGW("in->card_status or adev->card_status offline, try again");
1355 ret = -EAGAIN;
1356 goto error_config;
1357 }
1358
vivek mehta781065c2017-04-04 12:55:01 -07001359 /* Check if source matches incall recording usecase criteria */
1360 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1361 if (ret)
1362 goto error_config;
1363 else
1364 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1365
Eric Laurentb23d5282013-05-14 15:27:20 -07001366 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001367 if (in->pcm_device_id < 0) {
1368 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1369 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001370 ret = -EINVAL;
1371 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001373
1374 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001375 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1376 uc_info->id = in->usecase;
1377 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001378 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001379 uc_info->devices = in->device;
1380 uc_info->in_snd_device = SND_DEVICE_NONE;
1381 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001382
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001383 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001384
1385 audio_extn_perf_lock_acquire();
1386
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001387 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001388
Eric Laurent0e46adf2016-12-16 12:49:24 -08001389 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001390 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001391 ALOGE("%s: pcm stream not ready", __func__);
1392 goto error_open;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001393 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001394 ret = pcm_start(in->pcm);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001395 if (ret < 0) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001396 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1397 goto error_open;
1398 }
1399 } else {
1400 unsigned int flags = PCM_IN | PCM_MONOTONIC;
1401 unsigned int pcm_open_retry_count = 0;
1402
1403 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1404 flags |= PCM_MMAP | PCM_NOIRQ;
1405 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1406 } else if (in->realtime) {
1407 flags |= PCM_MMAP | PCM_NOIRQ;
1408 }
1409
1410 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
1411 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1412
1413 while (1) {
1414 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1415 flags, &in->config);
1416 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1417 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1418 if (in->pcm != NULL) {
1419 pcm_close(in->pcm);
1420 in->pcm = NULL;
1421 }
1422 if (pcm_open_retry_count-- == 0) {
1423 ret = -EIO;
1424 goto error_open;
1425 }
1426 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1427 continue;
1428 }
1429 break;
1430 }
1431
1432 ALOGV("%s: pcm_prepare", __func__);
1433 ret = pcm_prepare(in->pcm);
1434 if (ret < 0) {
1435 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001436 pcm_close(in->pcm);
1437 in->pcm = NULL;
1438 goto error_open;
1439 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001440 if (in->realtime) {
1441 ret = pcm_start(in->pcm);
1442 if (ret < 0) {
1443 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1444 pcm_close(in->pcm);
1445 in->pcm = NULL;
1446 goto error_open;
1447 }
1448 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001449 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001450 register_in_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001451 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001452 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001453
Eric Laurent0e46adf2016-12-16 12:49:24 -08001454 return 0;
Eric Laurentc8400632013-02-14 19:04:54 -08001455
1456error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001458 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001459
1460error_config:
1461 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001462 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001463 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464}
1465
Eric Laurenta1478072015-09-21 17:21:52 -07001466void lock_input_stream(struct stream_in *in)
1467{
1468 pthread_mutex_lock(&in->pre_lock);
1469 pthread_mutex_lock(&in->lock);
1470 pthread_mutex_unlock(&in->pre_lock);
1471}
1472
1473void lock_output_stream(struct stream_out *out)
1474{
1475 pthread_mutex_lock(&out->pre_lock);
1476 pthread_mutex_lock(&out->lock);
1477 pthread_mutex_unlock(&out->pre_lock);
1478}
1479
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001480/* must be called with out->lock locked */
1481static int send_offload_cmd_l(struct stream_out* out, int command)
1482{
1483 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1484
1485 ALOGVV("%s %d", __func__, command);
1486
1487 cmd->cmd = command;
1488 list_add_tail(&out->offload_cmd_list, &cmd->node);
1489 pthread_cond_signal(&out->offload_cond);
1490 return 0;
1491}
1492
1493/* must be called iwth out->lock locked */
1494static void stop_compressed_output_l(struct stream_out *out)
1495{
1496 out->offload_state = OFFLOAD_STATE_IDLE;
1497 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001498 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001499 if (out->compr != NULL) {
1500 compress_stop(out->compr);
1501 while (out->offload_thread_blocked) {
1502 pthread_cond_wait(&out->cond, &out->lock);
1503 }
1504 }
1505}
1506
1507static void *offload_thread_loop(void *context)
1508{
1509 struct stream_out *out = (struct stream_out *) context;
1510 struct listnode *item;
1511
1512 out->offload_state = OFFLOAD_STATE_IDLE;
1513 out->playback_started = 0;
1514
1515 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1516 set_sched_policy(0, SP_FOREGROUND);
1517 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1518
1519 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001520 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001521 for (;;) {
1522 struct offload_cmd *cmd = NULL;
1523 stream_callback_event_t event;
1524 bool send_callback = false;
1525
1526 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1527 __func__, list_empty(&out->offload_cmd_list),
1528 out->offload_state);
1529 if (list_empty(&out->offload_cmd_list)) {
1530 ALOGV("%s SLEEPING", __func__);
1531 pthread_cond_wait(&out->offload_cond, &out->lock);
1532 ALOGV("%s RUNNING", __func__);
1533 continue;
1534 }
1535
1536 item = list_head(&out->offload_cmd_list);
1537 cmd = node_to_item(item, struct offload_cmd, node);
1538 list_remove(item);
1539
1540 ALOGVV("%s STATE %d CMD %d out->compr %p",
1541 __func__, out->offload_state, cmd->cmd, out->compr);
1542
1543 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1544 free(cmd);
1545 break;
1546 }
1547
1548 if (out->compr == NULL) {
1549 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001550 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001551 pthread_cond_signal(&out->cond);
1552 continue;
1553 }
1554 out->offload_thread_blocked = true;
1555 pthread_mutex_unlock(&out->lock);
1556 send_callback = false;
1557 switch(cmd->cmd) {
1558 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1559 compress_wait(out->compr, -1);
1560 send_callback = true;
1561 event = STREAM_CBK_EVENT_WRITE_READY;
1562 break;
1563 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001564 compress_next_track(out->compr);
1565 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001566 send_callback = true;
1567 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001568 /* Resend the metadata for next iteration */
1569 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001570 break;
1571 case OFFLOAD_CMD_DRAIN:
1572 compress_drain(out->compr);
1573 send_callback = true;
1574 event = STREAM_CBK_EVENT_DRAIN_READY;
1575 break;
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07001576 case OFFLOAD_CMD_ERROR:
1577 send_callback = true;
1578 event = STREAM_CBK_EVENT_ERROR;
1579 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001580 default:
1581 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1582 break;
1583 }
Eric Laurenta1478072015-09-21 17:21:52 -07001584 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001585 out->offload_thread_blocked = false;
1586 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001587 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001588 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001589 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001590 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001591 free(cmd);
1592 }
1593
1594 pthread_cond_signal(&out->cond);
1595 while (!list_empty(&out->offload_cmd_list)) {
1596 item = list_head(&out->offload_cmd_list);
1597 list_remove(item);
1598 free(node_to_item(item, struct offload_cmd, node));
1599 }
1600 pthread_mutex_unlock(&out->lock);
1601
1602 return NULL;
1603}
1604
1605static int create_offload_callback_thread(struct stream_out *out)
1606{
1607 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1608 list_init(&out->offload_cmd_list);
1609 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1610 offload_thread_loop, out);
1611 return 0;
1612}
1613
1614static int destroy_offload_callback_thread(struct stream_out *out)
1615{
Eric Laurenta1478072015-09-21 17:21:52 -07001616 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001617 stop_compressed_output_l(out);
1618 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1619
1620 pthread_mutex_unlock(&out->lock);
1621 pthread_join(out->offload_thread, (void **) NULL);
1622 pthread_cond_destroy(&out->offload_cond);
1623
1624 return 0;
1625}
1626
Eric Laurent07eeafd2013-10-06 12:52:49 -07001627static bool allow_hdmi_channel_config(struct audio_device *adev)
1628{
1629 struct listnode *node;
1630 struct audio_usecase *usecase;
1631 bool ret = true;
1632
1633 list_for_each(node, &adev->usecase_list) {
1634 usecase = node_to_item(node, struct audio_usecase, list);
1635 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1636 /*
1637 * If voice call is already existing, do not proceed further to avoid
1638 * disabling/enabling both RX and TX devices, CSD calls, etc.
1639 * Once the voice call done, the HDMI channels can be configured to
1640 * max channels of remaining use cases.
1641 */
1642 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001643 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001644 __func__);
1645 ret = false;
1646 break;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08001647 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_HIFI) {
1648 ALOGV("%s: hifi playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001649 "no change in HDMI channels", __func__);
1650 ret = false;
1651 break;
1652 }
1653 }
1654 }
1655 return ret;
1656}
1657
1658static int check_and_set_hdmi_channels(struct audio_device *adev,
1659 unsigned int channels)
1660{
1661 struct listnode *node;
1662 struct audio_usecase *usecase;
1663
1664 /* Check if change in HDMI channel config is allowed */
1665 if (!allow_hdmi_channel_config(adev))
1666 return 0;
1667
1668 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001669 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001670 return 0;
1671 }
1672
1673 platform_set_hdmi_channels(adev->platform, channels);
1674 adev->cur_hdmi_channels = channels;
1675
1676 /*
1677 * Deroute all the playback streams routed to HDMI so that
1678 * the back end is deactivated. Note that backend will not
1679 * be deactivated if any one stream is connected to it.
1680 */
1681 list_for_each(node, &adev->usecase_list) {
1682 usecase = node_to_item(node, struct audio_usecase, list);
1683 if (usecase->type == PCM_PLAYBACK &&
1684 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001685 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001686 }
1687 }
1688
1689 /*
1690 * Enable all the streams disabled above. Now the HDMI backend
1691 * will be activated with new channel configuration
1692 */
1693 list_for_each(node, &adev->usecase_list) {
1694 usecase = node_to_item(node, struct audio_usecase, list);
1695 if (usecase->type == PCM_PLAYBACK &&
1696 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001697 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001698 }
1699 }
1700
1701 return 0;
1702}
1703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001704static int stop_output_stream(struct stream_out *out)
1705{
1706 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001707 struct audio_usecase *uc_info;
1708 struct audio_device *adev = out->dev;
1709
Eric Laurent994a6932013-07-17 11:51:42 -07001710 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001711 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712 uc_info = get_usecase_from_list(adev, out->usecase);
1713 if (uc_info == NULL) {
1714 ALOGE("%s: Could not find the usecase (%d) in the list",
1715 __func__, out->usecase);
1716 return -EINVAL;
1717 }
1718
Haynes Mathew George41f86652014-06-17 14:22:15 -07001719 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1720 if (adev->visualizer_stop_output != NULL)
1721 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1722 if (adev->offload_effects_stop_output != NULL)
1723 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1724 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001725
Eric Laurent150dbfe2013-02-27 14:31:02 -08001726 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001727 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001728
1729 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001730 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001732 list_remove(&uc_info->list);
1733 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734
Eric Laurent0499d4f2014-08-25 22:39:29 -05001735 audio_extn_extspk_update(adev->extspk);
1736
Eric Laurent07eeafd2013-10-06 12:52:49 -07001737 /* Must be called after removing the usecase from list */
1738 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1739 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1740
Eric Laurent994a6932013-07-17 11:51:42 -07001741 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 return ret;
1743}
1744
1745int start_output_stream(struct stream_out *out)
1746{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001748 struct audio_usecase *uc_info;
1749 struct audio_device *adev = out->dev;
1750
Eric Laurent994a6932013-07-17 11:51:42 -07001751 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001752 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07001753
1754 if (out->card_status == CARD_STATUS_OFFLINE ||
1755 adev->card_status == CARD_STATUS_OFFLINE) {
1756 ALOGW("out->card_status or adev->card_status offline, try again");
1757 ret = -EAGAIN;
1758 goto error_config;
1759 }
1760
Eric Laurentb23d5282013-05-14 15:27:20 -07001761 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762 if (out->pcm_device_id < 0) {
1763 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1764 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001765 ret = -EINVAL;
1766 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767 }
1768
1769 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1770 uc_info->id = out->usecase;
1771 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001772 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001773 uc_info->devices = out->devices;
1774 uc_info->in_snd_device = SND_DEVICE_NONE;
1775 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776
Eric Laurent07eeafd2013-10-06 12:52:49 -07001777 /* This must be called before adding this usecase to the list */
1778 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1779 check_and_set_hdmi_channels(adev, out->config.channels);
1780
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001781 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001783 audio_extn_perf_lock_acquire();
1784
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001785 select_devices(adev, out->usecase);
1786
Eric Laurent0499d4f2014-08-25 22:39:29 -05001787 audio_extn_extspk_update(adev->extspk);
1788
Andy Hung31aca912014-03-20 17:14:59 -07001789 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001790 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001791 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1792 out->pcm = NULL;
1793 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
1794 COMPRESS_IN, &out->compr_config);
1795 if (out->compr && !is_compress_ready(out->compr)) {
1796 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1797 compress_close(out->compr);
1798 out->compr = NULL;
1799 ret = -EIO;
1800 goto error_open;
1801 }
1802 if (out->offload_callback)
1803 compress_nonblock(out->compr, out->non_blocking);
1804
1805 if (adev->visualizer_start_output != NULL)
1806 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1807 if (adev->offload_effects_start_output != NULL)
1808 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
1809 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08001810 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08001811 ALOGE("%s: pcm stream not ready", __func__);
1812 goto error_open;
1813 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001814 ret = pcm_start(out->pcm);
1815 if (ret < 0) {
1816 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
1817 goto error_open;
1818 }
1819 } else {
Mikhail Naganov635e7432017-06-02 13:51:00 -07001820 unsigned int flags = PCM_OUT | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001821 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001822
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001823 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1824 flags |= PCM_MMAP | PCM_NOIRQ;
1825 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001826 } else if (out->realtime) {
1827 flags |= PCM_MMAP | PCM_NOIRQ;
Mikhail Naganov635e7432017-06-02 13:51:00 -07001828 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001829
1830 while (1) {
1831 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1832 flags, &out->config);
1833 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1834 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1835 if (out->pcm != NULL) {
1836 pcm_close(out->pcm);
1837 out->pcm = NULL;
1838 }
1839 if (pcm_open_retry_count-- == 0) {
1840 ret = -EIO;
1841 goto error_open;
1842 }
1843 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1844 continue;
1845 }
1846 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001847 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001848 ALOGV("%s: pcm_prepare", __func__);
1849 if (pcm_is_ready(out->pcm)) {
1850 ret = pcm_prepare(out->pcm);
1851 if (ret < 0) {
1852 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1853 pcm_close(out->pcm);
1854 out->pcm = NULL;
1855 goto error_open;
1856 }
1857 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08001858 if (out->realtime) {
1859 ret = pcm_start(out->pcm);
1860 if (ret < 0) {
1861 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
1862 pcm_close(out->pcm);
1863 out->pcm = NULL;
1864 goto error_open;
1865 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001866 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001867 }
Haynes Mathew Georgefbe87312016-08-01 19:29:27 -07001868 register_out_stream(out);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001869 audio_extn_perf_lock_release();
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08001870 audio_extn_tfa_98xx_enable_speaker();
vivek mehta4a824772017-06-08 19:05:49 -07001871 audio_extn_utils_send_app_type_gain(out->dev,
1872 out->app_type_cfg.app_type,
1873 &out->app_type_cfg.gain[0]);
Eric Laurent994a6932013-07-17 11:51:42 -07001874 ALOGV("%s: exit", __func__);
Eric Laurent0e46adf2016-12-16 12:49:24 -08001875 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001876error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001877 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001878 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001879error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001880 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001881}
1882
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001883static int check_input_parameters(uint32_t sample_rate,
1884 audio_format_t format,
1885 int channel_count)
1886{
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001887 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
1888 (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
1889 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED)) {
vivek mehtadae44712015-07-27 14:13:18 -07001890 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1891 return -EINVAL;
1892 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001893
vivek mehtadae44712015-07-27 14:13:18 -07001894 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001895 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001896 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1897 return -EINVAL;
1898 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001899
1900 switch (sample_rate) {
1901 case 8000:
1902 case 11025:
1903 case 12000:
1904 case 16000:
1905 case 22050:
1906 case 24000:
1907 case 32000:
1908 case 44100:
1909 case 48000:
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07001910 case 96000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001911 break;
1912 default:
vivek mehtadae44712015-07-27 14:13:18 -07001913 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914 return -EINVAL;
1915 }
1916
1917 return 0;
1918}
1919
vivek mehtaa68fea62017-06-08 19:04:02 -07001920static size_t get_stream_buffer_size(size_t duration_ms,
1921 uint32_t sample_rate,
1922 audio_format_t format,
1923 int channel_count,
1924 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001925{
1926 size_t size = 0;
1927
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001928 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1929 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930
vivek mehtaa68fea62017-06-08 19:04:02 -07001931 size = (sample_rate * duration_ms) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001932 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001933 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001934
1935 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936
Glenn Kasten4f993392014-05-14 07:30:48 -07001937 /* make sure the size is multiple of 32 bytes
1938 * At 48 kHz mono 16-bit PCM:
1939 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1940 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1941 */
1942 size += 0x1f;
1943 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001944
1945 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001946}
1947
1948static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1949{
1950 struct stream_out *out = (struct stream_out *)stream;
1951
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001952 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953}
1954
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001955static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956{
1957 return -ENOSYS;
1958}
1959
1960static size_t out_get_buffer_size(const struct audio_stream *stream)
1961{
1962 struct stream_out *out = (struct stream_out *)stream;
1963
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001964 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1965 return out->compr_config.fragment_size;
1966 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001967 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001968 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001969}
1970
1971static uint32_t out_get_channels(const struct audio_stream *stream)
1972{
1973 struct stream_out *out = (struct stream_out *)stream;
1974
1975 return out->channel_mask;
1976}
1977
1978static audio_format_t out_get_format(const struct audio_stream *stream)
1979{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001980 struct stream_out *out = (struct stream_out *)stream;
1981
1982 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983}
1984
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001985static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001986{
1987 return -ENOSYS;
1988}
1989
1990static int out_standby(struct audio_stream *stream)
1991{
1992 struct stream_out *out = (struct stream_out *)stream;
1993 struct audio_device *adev = out->dev;
Phil Burkbc991042017-02-24 08:06:44 -08001994 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001995
Eric Laurent994a6932013-07-17 11:51:42 -07001996 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001997 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998
Eric Laurenta1478072015-09-21 17:21:52 -07001999 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002001 if (adev->adm_deregister_stream)
2002 adev->adm_deregister_stream(adev->adm_data, out->handle);
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002003 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002004 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002005 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2006 if (out->pcm) {
2007 pcm_close(out->pcm);
2008 out->pcm = NULL;
2009 }
Eric Laurent0e46adf2016-12-16 12:49:24 -08002010 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002011 do_stop = out->playback_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002012 out->playback_started = false;
2013 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002014 } else {
2015 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002016 out->gapless_mdata.encoder_delay = 0;
2017 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002018 if (out->compr != NULL) {
2019 compress_close(out->compr);
2020 out->compr = NULL;
2021 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002022 }
Phil Burkbc991042017-02-24 08:06:44 -08002023 if (do_stop) {
2024 stop_output_stream(out);
2025 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002026 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002027 }
2028 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002029 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002030 return 0;
2031}
2032
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002033static int out_on_error(struct audio_stream *stream)
2034{
2035 struct stream_out *out = (struct stream_out *)stream;
2036 struct audio_device *adev = out->dev;
2037 bool do_standby = false;
2038
2039 lock_output_stream(out);
2040 if (!out->standby) {
2041 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2042 stop_compressed_output_l(out);
2043 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
2044 } else
2045 do_standby = true;
2046 }
2047 pthread_mutex_unlock(&out->lock);
2048
2049 if (do_standby)
2050 return out_standby(&out->stream.common);
2051
2052 return 0;
2053}
2054
Andy Hung7401c7c2016-09-21 12:41:21 -07002055static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002056{
Andy Hung7401c7c2016-09-21 12:41:21 -07002057 struct stream_out *out = (struct stream_out *)stream;
2058
2059 // We try to get the lock for consistency,
2060 // but it isn't necessary for these variables.
2061 // If we're not in standby, we may be blocked on a write.
2062 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
2063 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
2064 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
2065
2066 if (locked) {
Andy Hung7401c7c2016-09-21 12:41:21 -07002067 pthread_mutex_unlock(&out->lock);
Andy Hung7401c7c2016-09-21 12:41:21 -07002068 }
Andy Hunga452b0a2017-03-15 14:51:15 -07002069
2070 // dump error info
2071 (void)error_log_dump(
2072 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
Andy Hungfc044e12017-03-20 09:24:22 -07002073 // dump power info (out->power_log may be null)
Andy Hung62c9b882017-03-22 16:43:42 -07002074 (void)power_log_dump(
2075 out->power_log, fd, " " /* prefix */, POWER_LOG_LINES, 0 /* limit_ns */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 return 0;
2077}
2078
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002079static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
2080{
2081 int ret = 0;
2082 char value[32];
2083 struct compr_gapless_mdata tmp_mdata;
2084
2085 if (!out || !parms) {
2086 return -EINVAL;
2087 }
2088
2089 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
2090 if (ret >= 0) {
2091 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
2092 } else {
2093 return -EINVAL;
2094 }
2095
2096 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
2097 if (ret >= 0) {
2098 tmp_mdata.encoder_padding = atoi(value);
2099 } else {
2100 return -EINVAL;
2101 }
2102
2103 out->gapless_mdata = tmp_mdata;
2104 out->send_new_metadata = 1;
2105 ALOGV("%s new encoder delay %u and padding %u", __func__,
2106 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
2107
2108 return 0;
2109}
2110
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002111static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
2112{
2113 return out == adev->primary_output || out == adev->voice_tx_output;
2114}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
2117{
2118 struct stream_out *out = (struct stream_out *)stream;
2119 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002120 struct audio_usecase *usecase;
2121 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002122 struct str_parms *parms;
2123 char value[32];
2124 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002125 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07002126 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002127
Eric Laurent2e140aa2016-06-30 17:14:46 -07002128 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002129 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130 parms = str_parms_create_str(kvpairs);
2131 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2132 if (ret >= 0) {
2133 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07002134 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002135 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002136
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002137 /*
2138 * When HDMI cable is unplugged the music playback is paused and
2139 * the policy manager sends routing=0. But the audioflinger
2140 * continues to write data until standby time (3sec).
2141 * As the HDMI core is turned off, the write gets blocked.
2142 * Avoid this by routing audio to speaker until standby.
2143 */
2144 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
2145 val == AUDIO_DEVICE_NONE) {
2146 val = AUDIO_DEVICE_OUT_SPEAKER;
2147 }
2148
2149 /*
2150 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07002151 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002152 * the select_devices(). But how do we undo this?
2153 *
2154 * For example, music playback is active on headset (deep-buffer usecase)
2155 * and if we go to ringtones and select a ringtone, low-latency usecase
2156 * will be started on headset+speaker. As we can't enable headset+speaker
2157 * and headset devices at the same time, select_devices() switches the music
2158 * playback to headset+speaker while starting low-lateny usecase for ringtone.
2159 * So when the ringtone playback is completed, how do we undo the same?
2160 *
2161 * We are relying on the out_set_parameters() call on deep-buffer output,
2162 * once the ringtone playback is ended.
2163 * NOTE: We should not check if the current devices are same as new devices.
2164 * Because select_devices() must be called to switch back the music
2165 * playback to headset.
2166 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002167 audio_devices_t new_dev = val;
2168 if (new_dev != AUDIO_DEVICE_NONE) {
2169 bool same_dev = out->devices == new_dev;
2170 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002171
Eric Laurenta7657192014-10-09 21:09:33 -07002172 if (output_drives_call(adev, out)) {
2173 if (!voice_is_in_call(adev)) {
2174 if (adev->mode == AUDIO_MODE_IN_CALL) {
2175 adev->current_call_output = out;
2176 ret = voice_start_call(adev);
2177 }
2178 } else {
2179 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002180 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07002181 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002182 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002183
2184 if (!out->standby) {
2185 if (!same_dev) {
2186 ALOGV("update routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07002187 // inform adm before actual routing to prevent glitches.
2188 if (adev->adm_on_routing_change) {
2189 adev->adm_on_routing_change(adev->adm_data,
2190 out->handle);
2191 }
vivek mehta0d3637a2016-07-24 09:32:02 -07002192 }
2193 select_devices(adev, out->usecase);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08002194 audio_extn_tfa_98xx_update();
vivek mehta0d3637a2016-07-24 09:32:02 -07002195 }
2196
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002197 }
2198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002199 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002200 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002201
2202 /*handles device and call state changes*/
2203 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002205
2206 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2207 parse_compress_metadata(out, parms);
2208 }
2209
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002211 ALOGV("%s: exit: code(%d)", __func__, status);
2212 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002213}
2214
Haynes Mathew George569b7482017-05-08 14:44:27 -07002215static bool stream_get_parameter_channels(struct str_parms *query,
2216 struct str_parms *reply,
2217 audio_channel_mask_t *supported_channel_masks) {
2218 int ret = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 char value[256];
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002220 bool first = true;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002221 size_t i, j;
2222
2223 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
2224 ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 value[0] = '\0';
2226 i = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002227 while (supported_channel_masks[i] != 0) {
2228 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
2229 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 if (!first) {
2231 strcat(value, "|");
2232 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002233 strcat(value, channels_name_to_enum_table[j].name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234 first = false;
2235 break;
2236 }
2237 }
2238 i++;
2239 }
2240 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002241 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002242 return ret >= 0;
2243}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002244
Haynes Mathew George569b7482017-05-08 14:44:27 -07002245static bool stream_get_parameter_formats(struct str_parms *query,
2246 struct str_parms *reply,
2247 audio_format_t *supported_formats) {
2248 int ret = -1;
2249 char value[256];
2250 int i;
2251
2252 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
2253 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002254 value[0] = '\0';
Haynes Mathew George569b7482017-05-08 14:44:27 -07002255 switch (supported_formats[0]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002256 case AUDIO_FORMAT_PCM_16_BIT:
2257 strcat(value, "AUDIO_FORMAT_PCM_16_BIT");
2258 break;
2259 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
2260 strcat(value, "AUDIO_FORMAT_PCM_24_BIT_PACKED");
2261 break;
2262 case AUDIO_FORMAT_PCM_32_BIT:
2263 strcat(value, "AUDIO_FORMAT_PCM_32_BIT");
2264 break;
2265 default:
2266 ALOGE("%s: unsupported format %#x", __func__,
Haynes Mathew George569b7482017-05-08 14:44:27 -07002267 supported_formats[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002268 break;
2269 }
2270 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002271 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002272 return ret >= 0;
2273}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002274
Haynes Mathew George569b7482017-05-08 14:44:27 -07002275static bool stream_get_parameter_rates(struct str_parms *query,
2276 struct str_parms *reply,
2277 uint32_t *supported_sample_rates) {
2278
2279 int i;
2280 char value[256];
2281 int ret = -1;
2282 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
2283 ret = 0;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002284 value[0] = '\0';
2285 i=0;
2286 int cursor = 0;
Haynes Mathew George569b7482017-05-08 14:44:27 -07002287 while (supported_sample_rates[i]) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002288 int avail = sizeof(value) - cursor;
2289 ret = snprintf(value + cursor, avail, "%s%d",
2290 cursor > 0 ? "|" : "",
Haynes Mathew George569b7482017-05-08 14:44:27 -07002291 supported_sample_rates[i]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002292 if (ret < 0 || ret >= avail) {
2293 // if cursor is at the last element of the array
2294 // overwrite with \0 is duplicate work as
2295 // snprintf already put a \0 in place.
2296 // else
2297 // we had space to write the '|' at value[cursor]
2298 // (which will be overwritten) or no space to fill
2299 // the first element (=> cursor == 0)
2300 value[cursor] = '\0';
2301 break;
2302 }
2303 cursor += ret;
2304 ++i;
2305 }
2306 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
2307 value);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002308 }
Haynes Mathew George569b7482017-05-08 14:44:27 -07002309 return ret >= 0;
2310}
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002311
Haynes Mathew George569b7482017-05-08 14:44:27 -07002312static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2313{
2314 struct stream_out *out = (struct stream_out *)stream;
2315 struct str_parms *query = str_parms_create_str(keys);
2316 char *str;
2317 struct str_parms *reply = str_parms_create();
2318 bool replied = false;
2319 ALOGV("%s: enter: keys - %s", __func__, keys);
2320
2321 replied |= stream_get_parameter_channels(query, reply,
2322 &out->supported_channel_masks[0]);
2323 replied |= stream_get_parameter_formats(query, reply,
2324 &out->supported_formats[0]);
2325 replied |= stream_get_parameter_rates(query, reply,
2326 &out->supported_sample_rates[0]);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002327 if (replied) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002328 str = str_parms_to_str(reply);
2329 } else {
Kevin Rocardedf0b4c2017-05-05 09:08:11 -07002330 str = strdup("");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002331 }
2332 str_parms_destroy(query);
2333 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002334 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 return str;
2336}
2337
2338static uint32_t out_get_latency(const struct audio_stream_out *stream)
2339{
Haynes Mathew George03c40102016-01-29 17:57:48 -08002340 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002341 struct stream_out *out = (struct stream_out *)stream;
2342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
2344 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002345 else if ((out->realtime) ||
2346 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002347 // since the buffer won't be filled up faster than realtime,
2348 // return a smaller number
2349 period_ms = (out->af_period_multiplier * out->config.period_size *
2350 1000) / (out->config.rate);
2351 hw_delay = platform_render_latency(out->usecase)/1000;
2352 return period_ms + hw_delay;
2353 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354
2355 return (out->config.period_count * out->config.period_size * 1000) /
2356 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002357}
2358
2359static int out_set_volume(struct audio_stream_out *stream, float left,
2360 float right)
2361{
Eric Laurenta9024de2013-04-04 09:19:12 -07002362 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002363 int volume[2];
2364
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08002365 if (out->usecase == USECASE_AUDIO_PLAYBACK_HIFI) {
Eric Laurenta9024de2013-04-04 09:19:12 -07002366 /* only take left channel into account: the API is for stereo anyway */
2367 out->muted = (left == 0.0f);
2368 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2370 const char *mixer_ctl_name = "Compress Playback Volume";
2371 struct audio_device *adev = out->dev;
2372 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002373 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2374 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07002375 /* try with the control based on device id */
2376 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2377 PCM_PLAYBACK);
2378 char ctl_name[128] = {0};
2379 snprintf(ctl_name, sizeof(ctl_name),
2380 "Compress Playback %d Volume", pcm_device_id);
2381 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
2382 if (!ctl) {
2383 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
2384 return -EINVAL;
2385 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002386 }
2387 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2388 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2389 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2390 return 0;
vivek mehtaa68fea62017-06-08 19:04:02 -07002391 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
vivek mehta4a824772017-06-08 19:05:49 -07002392 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
2393 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
2394 if (!out->standby) {
2395 // if in standby, cached volume will be sent after stream is opened
2396 audio_extn_utils_send_app_type_gain(out->dev,
2397 out->app_type_cfg.app_type,
2398 &out->app_type_cfg.gain[0]);
vivek mehtaa68fea62017-06-08 19:04:02 -07002399 }
vivek mehtaa68fea62017-06-08 19:04:02 -07002400 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002401 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002402
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403 return -ENOSYS;
2404}
2405
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002406// note: this call is safe only if the stream_cb is
2407// removed first in close_output_stream (as is done now).
2408static void out_snd_mon_cb(void * stream, struct str_parms * parms)
2409{
2410 if (!stream || !parms)
2411 return;
2412
2413 struct stream_out *out = (struct stream_out *)stream;
2414 struct audio_device *adev = out->dev;
2415
2416 card_status_t status;
2417 int card;
2418 if (parse_snd_card_status(parms, &card, &status) < 0)
2419 return;
2420
2421 pthread_mutex_lock(&adev->lock);
2422 bool valid_cb = (card == adev->snd_card);
2423 pthread_mutex_unlock(&adev->lock);
2424
2425 if (!valid_cb)
2426 return;
2427
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002428 lock_output_stream(out);
2429 if (out->card_status != status)
2430 out->card_status = status;
2431 pthread_mutex_unlock(&out->lock);
2432
Haynes Mathew George3ddd3bd2016-07-07 20:01:53 -07002433 ALOGW("out_snd_mon_cb for card %d usecase %s, status %s", card,
2434 use_case_table[out->usecase],
2435 status == CARD_STATUS_OFFLINE ? "offline" : "online");
2436
2437 if (status == CARD_STATUS_OFFLINE)
2438 out_on_error(stream);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07002439
2440 return;
2441}
2442
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002443#ifdef NO_AUDIO_OUT
2444static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002445 const void *buffer __unused, size_t bytes)
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002446{
2447 struct stream_out *out = (struct stream_out *)stream;
2448
2449 /* No Output device supported other than BT for playback.
2450 * Sleep for the amount of buffer duration
2451 */
Eric Laurenta1478072015-09-21 17:21:52 -07002452 lock_output_stream(out);
Ariel Gertzensteinc2c11742016-11-14 18:08:28 -05002453 usleep(bytes * 1000000 / audio_stream_out_frame_size(
2454 (const struct audio_stream_out *)&out->stream) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002455 out_get_sample_rate(&out->stream.common));
2456 pthread_mutex_unlock(&out->lock);
2457 return bytes;
2458}
2459#endif
2460
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2462 size_t bytes)
2463{
2464 struct stream_out *out = (struct stream_out *)stream;
2465 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07002466 ssize_t ret = 0;
Andy Hung7401c7c2016-09-21 12:41:21 -07002467 int error_code = ERROR_CODE_STANDBY;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468
Eric Laurenta1478072015-09-21 17:21:52 -07002469 lock_output_stream(out);
vivek mehtae3afca22017-04-11 17:13:50 -07002470 // this is always nonzero
2471 const int frame_size = audio_stream_out_frame_size(stream);
2472
Eric Laurent0e46adf2016-12-16 12:49:24 -08002473 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
2474 error_code = ERROR_CODE_WRITE;
2475 goto exit;
2476 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002477 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002478 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002479 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002481 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002482 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002484 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 goto exit;
2486 }
vivek mehtafb4d7bd2016-04-29 03:16:47 -07002487
2488 if (last_known_cal_step != -1) {
2489 ALOGD("%s: retry previous failed cal level set", __func__);
2490 audio_hw_send_gain_dep_calibration(last_known_cal_step);
2491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002494 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08002495 ALOGVV("%s: writing buffer (%zu bytes) to compress device", __func__, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002496 if (out->send_new_metadata) {
2497 ALOGVV("send new gapless metadata");
2498 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2499 out->send_new_metadata = 0;
2500 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002501 unsigned int avail;
2502 struct timespec tstamp;
2503 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
2504 /* Do not limit write size if the available frames count is unknown */
2505 if (ret != 0) {
2506 avail = bytes;
2507 }
2508 if (avail == 0) {
2509 ret = 0;
2510 } else {
2511 if (avail > bytes) {
2512 avail = bytes;
2513 }
2514 ret = compress_write(out->compr, buffer, avail);
2515 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
2516 __func__, avail, ret);
2517 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002518
Eric Laurent6e895242013-09-05 16:10:57 -07002519 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002520 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
2521 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08002522 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002523 compress_start(out->compr);
2524 out->playback_started = 1;
2525 out->offload_state = OFFLOAD_STATE_PLAYING;
2526 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002527 if (ret < 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002528 error_log_log(out->error_log, ERROR_CODE_WRITE, audio_utils_get_real_time_ns());
Andy Hungdacb45c2017-03-31 15:38:14 -07002529 } else {
2530 out->written += ret; // accumulate bytes written for offload.
Andy Hung7401c7c2016-09-21 12:41:21 -07002531 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002532 pthread_mutex_unlock(&out->lock);
Andy Hungfc044e12017-03-20 09:24:22 -07002533 // TODO: consider logging offload pcm
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002534 return ret;
2535 } else {
Andy Hung7401c7c2016-09-21 12:41:21 -07002536 error_code = ERROR_CODE_WRITE;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002537 if (out->pcm) {
2538 if (out->muted)
2539 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002540
Eric Laurent0e46adf2016-12-16 12:49:24 -08002541 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002542
Haynes Mathew George03c40102016-01-29 17:57:48 -08002543 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
2544 out->config.rate;
2545 request_out_focus(out, ns);
2546
2547 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
2548 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002549 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002550 else
2551 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002552
Haynes Mathew George03c40102016-01-29 17:57:48 -08002553 release_out_focus(out, ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002554 } else {
2555 LOG_ALWAYS_FATAL("out->pcm is NULL after starting output stream");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557 }
2558
2559exit:
Andy Hungda9b56b2016-09-16 20:06:35 -07002560 // For PCM we always consume the buffer and return #bytes regardless of ret.
2561 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2562 out->written += bytes / (out->config.channels * sizeof(short));
2563 }
Andy Hung7401c7c2016-09-21 12:41:21 -07002564 long long sleeptime_us = 0;
Andy Hung9e737de2017-05-22 10:51:22 -07002565
2566 // only get time if needed for logging, as it is a system call on 32 bit devices.
2567 // TODO: Consider always enabling for 64 bit vDSO using compile time check on __LP64__.
2568 const int64_t now_ns = out->power_log != 0 || (ret != 0 && out->error_log != 0)
2569 ? audio_utils_get_real_time_ns() : 0;
Andy Hungfc044e12017-03-20 09:24:22 -07002570
Andy Hung7401c7c2016-09-21 12:41:21 -07002571 if (ret != 0) {
Andy Hunga452b0a2017-03-15 14:51:15 -07002572 error_log_log(out->error_log, error_code, now_ns);
Andy Hung7401c7c2016-09-21 12:41:21 -07002573 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2574 ALOGE_IF(out->pcm != NULL,
2575 "%s: error %zd - %s", __func__, ret, pcm_get_error(out->pcm));
Andy Hungfc044e12017-03-20 09:24:22 -07002576 sleeptime_us = bytes * 1000000LL / frame_size /
Andy Hung7401c7c2016-09-21 12:41:21 -07002577 out_get_sample_rate(&out->stream.common);
2578 // usleep not guaranteed for values over 1 second but we don't limit here.
2579 }
2580 }
Andy Hungda9b56b2016-09-16 20:06:35 -07002581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 pthread_mutex_unlock(&out->lock);
2583
2584 if (ret != 0) {
Haynes Mathew Georgef9c7aae2016-09-20 14:12:41 -07002585 out_on_error(&out->stream.common);
Andy Hung7401c7c2016-09-21 12:41:21 -07002586 if (sleeptime_us != 0)
2587 usleep(sleeptime_us);
Andy Hungfc044e12017-03-20 09:24:22 -07002588 } else {
2589 // only log if the data is properly written (out->power_log may be null)
2590 power_log_log(out->power_log, buffer, bytes / frame_size, now_ns);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 }
2592 return bytes;
2593}
2594
2595static int out_get_render_position(const struct audio_stream_out *stream,
2596 uint32_t *dsp_frames)
2597{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002598 struct stream_out *out = (struct stream_out *)stream;
2599 *dsp_frames = 0;
2600 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07002601 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002602 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002603 unsigned long frames = 0;
2604 // TODO: check return value
2605 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
2606 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002607 ALOGVV("%s rendered frames %d sample_rate %d",
2608 __func__, *dsp_frames, out->sample_rate);
2609 }
2610 pthread_mutex_unlock(&out->lock);
2611 return 0;
2612 } else
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002613 return -ENODATA;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614}
2615
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002616static int out_add_audio_effect(const struct audio_stream *stream __unused,
2617 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618{
2619 return 0;
2620}
2621
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002622static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2623 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624{
2625 return 0;
2626}
2627
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002628static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2629 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002631 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002632}
2633
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002634static int out_get_presentation_position(const struct audio_stream_out *stream,
2635 uint64_t *frames, struct timespec *timestamp)
2636{
2637 struct stream_out *out = (struct stream_out *)stream;
Kevin Rocard75d41bf2017-05-02 16:38:39 -07002638 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07002639 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002640
Eric Laurenta1478072015-09-21 17:21:52 -07002641 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002642
Eric Laurent949a0892013-09-20 09:20:13 -07002643 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2644 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002645 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002646 compress_get_tstamp(out->compr, &dsp_frames,
2647 &out->sample_rate);
2648 ALOGVV("%s rendered frames %ld sample_rate %d",
2649 __func__, dsp_frames, out->sample_rate);
2650 *frames = dsp_frames;
2651 ret = 0;
2652 /* this is the best we can do */
2653 clock_gettime(CLOCK_MONOTONIC, timestamp);
2654 }
2655 } else {
2656 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002657 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002658 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2659 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002660 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002661 // This adjustment accounts for buffering after app processor.
2662 // It is based on estimated DSP latency per use case, rather than exact.
2663 signed_frames -=
2664 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2665
Eric Laurent949a0892013-09-20 09:20:13 -07002666 // It would be unusual for this value to be negative, but check just in case ...
2667 if (signed_frames >= 0) {
2668 *frames = signed_frames;
2669 ret = 0;
2670 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002671 }
2672 }
2673 }
2674
2675 pthread_mutex_unlock(&out->lock);
2676
2677 return ret;
2678}
2679
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002680static int out_set_callback(struct audio_stream_out *stream,
2681 stream_callback_t callback, void *cookie)
2682{
2683 struct stream_out *out = (struct stream_out *)stream;
2684
2685 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002686 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002687 out->offload_callback = callback;
2688 out->offload_cookie = cookie;
2689 pthread_mutex_unlock(&out->lock);
2690 return 0;
2691}
2692
2693static int out_pause(struct audio_stream_out* stream)
2694{
2695 struct stream_out *out = (struct stream_out *)stream;
2696 int status = -ENOSYS;
2697 ALOGV("%s", __func__);
2698 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002699 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002700 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2701 status = compress_pause(out->compr);
2702 out->offload_state = OFFLOAD_STATE_PAUSED;
2703 }
2704 pthread_mutex_unlock(&out->lock);
2705 }
2706 return status;
2707}
2708
2709static int out_resume(struct audio_stream_out* stream)
2710{
2711 struct stream_out *out = (struct stream_out *)stream;
2712 int status = -ENOSYS;
2713 ALOGV("%s", __func__);
2714 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2715 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002716 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002717 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2718 status = compress_resume(out->compr);
2719 out->offload_state = OFFLOAD_STATE_PLAYING;
2720 }
2721 pthread_mutex_unlock(&out->lock);
2722 }
2723 return status;
2724}
2725
2726static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2727{
2728 struct stream_out *out = (struct stream_out *)stream;
2729 int status = -ENOSYS;
2730 ALOGV("%s", __func__);
2731 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002732 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002733 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2734 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2735 else
2736 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2737 pthread_mutex_unlock(&out->lock);
2738 }
2739 return status;
2740}
2741
2742static int out_flush(struct audio_stream_out* stream)
2743{
2744 struct stream_out *out = (struct stream_out *)stream;
2745 ALOGV("%s", __func__);
2746 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002747 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002748 stop_compressed_output_l(out);
2749 pthread_mutex_unlock(&out->lock);
2750 return 0;
2751 }
2752 return -ENOSYS;
2753}
2754
Eric Laurent0e46adf2016-12-16 12:49:24 -08002755static int out_stop(const struct audio_stream_out* stream)
2756{
2757 struct stream_out *out = (struct stream_out *)stream;
2758 struct audio_device *adev = out->dev;
2759 int ret = -ENOSYS;
2760
2761 ALOGV("%s", __func__);
2762 pthread_mutex_lock(&adev->lock);
2763 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2764 out->playback_started && out->pcm != NULL) {
2765 pcm_stop(out->pcm);
2766 ret = stop_output_stream(out);
Phil Burkbc991042017-02-24 08:06:44 -08002767 out->playback_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002768 }
2769 pthread_mutex_unlock(&adev->lock);
2770 return ret;
2771}
2772
2773static int out_start(const struct audio_stream_out* stream)
2774{
2775 struct stream_out *out = (struct stream_out *)stream;
2776 struct audio_device *adev = out->dev;
2777 int ret = -ENOSYS;
2778
2779 ALOGV("%s", __func__);
2780 pthread_mutex_lock(&adev->lock);
2781 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
2782 !out->playback_started && out->pcm != NULL) {
2783 ret = start_output_stream(out);
2784 if (ret == 0) {
2785 out->playback_started = true;
2786 }
2787 }
2788 pthread_mutex_unlock(&adev->lock);
2789 return ret;
2790}
2791
Phil Burkbc991042017-02-24 08:06:44 -08002792/*
2793 * Modify config->period_count based on min_size_frames
2794 */
2795static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
2796{
2797 int periodCountRequested = (min_size_frames + config->period_size - 1)
2798 / config->period_size;
2799 int periodCount = MMAP_PERIOD_COUNT_MIN;
2800
2801 ALOGV("%s original config.period_size = %d config.period_count = %d",
2802 __func__, config->period_size, config->period_count);
2803
2804 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
2805 periodCount *= 2;
2806 }
2807 config->period_count = periodCount;
2808
2809 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
2810}
2811
Eric Laurent0e46adf2016-12-16 12:49:24 -08002812static int out_create_mmap_buffer(const struct audio_stream_out *stream,
2813 int32_t min_size_frames,
2814 struct audio_mmap_buffer_info *info)
2815{
2816 struct stream_out *out = (struct stream_out *)stream;
2817 struct audio_device *adev = out->dev;
2818 int ret = 0;
2819 unsigned int offset1;
2820 unsigned int frames1;
2821 const char *step = "";
2822
2823 ALOGV("%s", __func__);
2824 pthread_mutex_lock(&adev->lock);
2825
2826 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002827 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002828 ret = -EINVAL;
2829 goto exit;
2830 }
2831 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08002832 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002833 ret = -ENOSYS;
2834 goto exit;
2835 }
2836 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
2837 if (out->pcm_device_id < 0) {
2838 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
2839 __func__, out->pcm_device_id, out->usecase);
2840 ret = -EINVAL;
2841 goto exit;
2842 }
Phil Burkbc991042017-02-24 08:06:44 -08002843
2844 adjust_mmap_period_count(&out->config, min_size_frames);
2845
Eric Laurent0e46adf2016-12-16 12:49:24 -08002846 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2847 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
2848 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
2849 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
2850 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
2851 step = "open";
2852 ret = -ENODEV;
2853 goto exit;
2854 }
2855 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
2856 if (ret < 0) {
2857 step = "begin";
2858 goto exit;
2859 }
2860 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
2861 info->burst_size_frames = out->config.period_size;
2862 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
2863
2864 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
2865 info->buffer_size_frames));
2866
2867 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
2868 if (ret < 0) {
2869 step = "commit";
2870 goto exit;
2871 }
Phil Burkbc991042017-02-24 08:06:44 -08002872
2873 out->standby = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002874 ret = 0;
2875
2876 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
2877 __func__, info->shared_memory_address, info->buffer_size_frames);
2878
2879exit:
2880 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08002881 if (out->pcm == NULL) {
2882 ALOGE("%s: %s - %d", __func__, step, ret);
2883 } else {
2884 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08002885 pcm_close(out->pcm);
2886 out->pcm = NULL;
2887 }
2888 }
2889 pthread_mutex_unlock(&adev->lock);
2890 return ret;
2891}
2892
2893static int out_get_mmap_position(const struct audio_stream_out *stream,
2894 struct audio_mmap_position *position)
2895{
2896 struct stream_out *out = (struct stream_out *)stream;
2897 ALOGVV("%s", __func__);
2898 if (position == NULL) {
2899 return -EINVAL;
2900 }
2901 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
2902 return -ENOSYS;
2903 }
2904 if (out->pcm == NULL) {
2905 return -ENOSYS;
2906 }
2907
2908 struct timespec ts = { 0, 0 };
2909 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
2910 if (ret < 0) {
2911 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
2912 return ret;
2913 }
Andy Hungfc044e12017-03-20 09:24:22 -07002914 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08002915 return 0;
2916}
2917
2918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002919/** audio_stream_in implementation **/
2920static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2921{
2922 struct stream_in *in = (struct stream_in *)stream;
2923
2924 return in->config.rate;
2925}
2926
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002927static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928{
2929 return -ENOSYS;
2930}
2931
2932static size_t in_get_buffer_size(const struct audio_stream *stream)
2933{
2934 struct stream_in *in = (struct stream_in *)stream;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002935 return in->config.period_size * in->af_period_multiplier *
2936 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002937}
2938
2939static uint32_t in_get_channels(const struct audio_stream *stream)
2940{
2941 struct stream_in *in = (struct stream_in *)stream;
2942
2943 return in->channel_mask;
2944}
2945
vivek mehta4ed66e62016-04-15 23:33:34 -07002946static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947{
vivek mehta4ed66e62016-04-15 23:33:34 -07002948 struct stream_in *in = (struct stream_in *)stream;
2949 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002950}
2951
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002952static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002953{
2954 return -ENOSYS;
2955}
2956
2957static int in_standby(struct audio_stream *stream)
2958{
2959 struct stream_in *in = (struct stream_in *)stream;
2960 struct audio_device *adev = in->dev;
2961 int status = 0;
Phil Burkbc991042017-02-24 08:06:44 -08002962 bool do_stop = true;
2963
Eric Laurent994a6932013-07-17 11:51:42 -07002964 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002965
2966 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002967
2968 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002969 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002970 audio_extn_sound_trigger_stop_lab(in);
2971 in->standby = true;
2972 }
2973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002974 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002975 if (adev->adm_deregister_stream)
2976 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2977
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002978 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002979 in->standby = true;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002980 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Phil Burkbc991042017-02-24 08:06:44 -08002981 do_stop = in->capture_started;
Eric Laurent0e46adf2016-12-16 12:49:24 -08002982 in->capture_started = false;
2983 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002984 if (in->pcm) {
2985 pcm_close(in->pcm);
2986 in->pcm = NULL;
2987 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002988 adev->enable_voicerx = false;
2989 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Phil Burkbc991042017-02-24 08:06:44 -08002990 if (do_stop) {
2991 status = stop_input_stream(in);
2992 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08002993 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 }
2995 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002996 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997 return status;
2998}
2999
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003000static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001{
3002 return 0;
3003}
3004
3005static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
3006{
3007 struct stream_in *in = (struct stream_in *)stream;
3008 struct audio_device *adev = in->dev;
3009 struct str_parms *parms;
3010 char *str;
3011 char value[32];
3012 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07003013 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014
Eric Laurent994a6932013-07-17 11:51:42 -07003015 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003016 parms = str_parms_create_str(kvpairs);
3017
3018 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
3019
Eric Laurenta1478072015-09-21 17:21:52 -07003020 lock_input_stream(in);
3021
Eric Laurent150dbfe2013-02-27 14:31:02 -08003022 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 if (ret >= 0) {
3024 val = atoi(value);
3025 /* no audio source uses val == 0 */
3026 if ((in->source != val) && (val != 0)) {
3027 in->source = val;
3028 }
3029 }
3030
3031 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07003032
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033 if (ret >= 0) {
3034 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003035 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003036 in->device = val;
3037 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08003038 if (!in->standby) {
3039 ALOGV("update input routing change");
Haynes Mathew George104fdfd2016-07-01 16:57:24 -07003040 // inform adm before actual routing to prevent glitches.
3041 if (adev->adm_on_routing_change) {
3042 adev->adm_on_routing_change(adev->adm_data,
3043 in->capture_handle);
3044 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003045 select_devices(adev, in->usecase);
3046 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047 }
3048 }
3049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003051 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052
3053 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07003054 ALOGV("%s: exit: status(%d)", __func__, status);
3055 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003056}
3057
Haynes Mathew George569b7482017-05-08 14:44:27 -07003058static char* in_get_parameters(const struct audio_stream *stream,
3059 const char *keys)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060{
Haynes Mathew George569b7482017-05-08 14:44:27 -07003061 struct stream_in *in = (struct stream_in *)stream;
3062 struct str_parms *query = str_parms_create_str(keys);
3063 char *str;
3064 struct str_parms *reply = str_parms_create();
3065 bool replied = false;
3066
3067 ALOGV("%s: enter: keys - %s", __func__, keys);
3068 replied |= stream_get_parameter_channels(query, reply,
3069 &in->supported_channel_masks[0]);
3070 replied |= stream_get_parameter_formats(query, reply,
3071 &in->supported_formats[0]);
3072 replied |= stream_get_parameter_rates(query, reply,
3073 &in->supported_sample_rates[0]);
3074 if (replied) {
3075 str = str_parms_to_str(reply);
3076 } else {
3077 str = strdup(keys);
3078 }
3079 str_parms_destroy(query);
3080 str_parms_destroy(reply);
3081 ALOGV("%s: exit: returns - %s", __func__, str);
3082 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083}
3084
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003085static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003086{
Kevin Rocard75d41bf2017-05-02 16:38:39 -07003087 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088}
3089
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003090static void in_snd_mon_cb(void * stream, struct str_parms * parms)
3091{
3092 if (!stream || !parms)
3093 return;
3094
3095 struct stream_in *in = (struct stream_in *)stream;
3096 struct audio_device *adev = in->dev;
3097
3098 card_status_t status;
3099 int card;
3100 if (parse_snd_card_status(parms, &card, &status) < 0)
3101 return;
3102
3103 pthread_mutex_lock(&adev->lock);
3104 bool valid_cb = (card == adev->snd_card);
3105 pthread_mutex_unlock(&adev->lock);
3106
3107 if (!valid_cb)
3108 return;
3109
3110 lock_input_stream(in);
3111 if (in->card_status != status)
3112 in->card_status = status;
3113 pthread_mutex_unlock(&in->lock);
3114
3115 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
3116 use_case_table[in->usecase],
3117 status == CARD_STATUS_OFFLINE ? "offline" : "online");
3118
3119 // a better solution would be to report error back to AF and let
3120 // it put the stream to standby
3121 if (status == CARD_STATUS_OFFLINE)
3122 in_standby(&in->stream.common);
3123
3124 return;
3125}
3126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003127static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
3128 size_t bytes)
3129{
3130 struct stream_in *in = (struct stream_in *)stream;
3131 struct audio_device *adev = in->dev;
3132 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07003133 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134
Eric Laurenta1478072015-09-21 17:21:52 -07003135 lock_input_stream(in);
3136
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003137 if (in->is_st_session) {
Eric Laurent0e46adf2016-12-16 12:49:24 -08003138 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003139 /* Read from sound trigger HAL */
3140 audio_extn_sound_trigger_read(in, buffer, bytes);
3141 pthread_mutex_unlock(&in->lock);
3142 return bytes;
3143 }
3144
Eric Laurent0e46adf2016-12-16 12:49:24 -08003145 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
3146 ret = -ENOSYS;
3147 goto exit;
3148 }
3149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003150 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003151 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08003153 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 goto exit;
3156 }
3157 in->standby = 0;
3158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159
Haynes Mathew George03c40102016-01-29 17:57:48 -08003160 //what's the duration requested by the client?
3161 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
3162 in->config.rate;
3163 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003164
Haynes Mathew George03c40102016-01-29 17:57:48 -08003165 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003166 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08003167 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003168 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07003169 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003170 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003171 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003172 if (ret < 0) {
3173 ALOGE("Failed to read w/err %s", strerror(errno));
3174 ret = -errno;
3175 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003176 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
3177 if (bytes % 4 == 0) {
3178 /* data from DSP comes in 24_8 format, convert it to 8_24 */
3179 int_buf_stream = buffer;
3180 for (size_t itt=0; itt < bytes/4 ; itt++) {
3181 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07003182 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07003183 } else {
3184 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
3185 ret = -EINVAL;
3186 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07003187 }
3188 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003189 }
3190
Haynes Mathew George03c40102016-01-29 17:57:48 -08003191 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003192
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003193 /*
3194 * Instead of writing zeroes here, we could trust the hardware
3195 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003196 * 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 -08003197 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07003198 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199 memset(buffer, 0, bytes);
3200
3201exit:
3202 pthread_mutex_unlock(&in->lock);
3203
3204 if (ret != 0) {
3205 in_standby(&in->stream.common);
3206 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07003207 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003208 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08003209 memset(buffer, 0, bytes); // clear return data
3210 }
3211 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08003212 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003213 }
3214 return bytes;
3215}
3216
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003217static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003218{
3219 return 0;
3220}
3221
Andy Hung6ebe5962016-01-15 17:46:57 -08003222static int in_get_capture_position(const struct audio_stream_in *stream,
3223 int64_t *frames, int64_t *time)
3224{
3225 if (stream == NULL || frames == NULL || time == NULL) {
3226 return -EINVAL;
3227 }
3228 struct stream_in *in = (struct stream_in *)stream;
3229 int ret = -ENOSYS;
3230
3231 lock_input_stream(in);
3232 if (in->pcm) {
3233 struct timespec timestamp;
3234 unsigned int avail;
3235 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
3236 *frames = in->frames_read + avail;
3237 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
3238 ret = 0;
3239 }
3240 }
3241 pthread_mutex_unlock(&in->lock);
3242 return ret;
3243}
3244
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003245static int add_remove_audio_effect(const struct audio_stream *stream,
3246 effect_handle_t effect,
3247 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003248{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003249 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003250 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003251 int status = 0;
3252 effect_descriptor_t desc;
3253
3254 status = (*effect)->get_descriptor(effect, &desc);
3255 if (status != 0)
3256 return status;
3257
Eric Laurenta1478072015-09-21 17:21:52 -07003258 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003259 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07003260 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07003261 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07003262 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003263 in->enable_aec != enable &&
3264 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
3265 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003266 if (!enable)
3267 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07003268 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
3269 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
3270 adev->enable_voicerx = enable;
3271 struct audio_usecase *usecase;
3272 struct listnode *node;
3273 list_for_each(node, &adev->usecase_list) {
3274 usecase = node_to_item(node, struct audio_usecase, list);
3275 if (usecase->type == PCM_PLAYBACK) {
3276 select_devices(adev, usecase->id);
3277 break;
3278 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05003279 }
3280 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003281 if (!in->standby)
3282 select_devices(in->dev, in->usecase);
3283 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07003284 if (in->enable_ns != enable &&
3285 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
3286 in->enable_ns = enable;
3287 if (!in->standby)
3288 select_devices(in->dev, in->usecase);
3289 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003290 pthread_mutex_unlock(&in->dev->lock);
3291 pthread_mutex_unlock(&in->lock);
3292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293 return 0;
3294}
3295
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003296static int in_add_audio_effect(const struct audio_stream *stream,
3297 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298{
Eric Laurent994a6932013-07-17 11:51:42 -07003299 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003300 return add_remove_audio_effect(stream, effect, true);
3301}
3302
3303static int in_remove_audio_effect(const struct audio_stream *stream,
3304 effect_handle_t effect)
3305{
Eric Laurent994a6932013-07-17 11:51:42 -07003306 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07003307 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003308}
3309
Eric Laurent0e46adf2016-12-16 12:49:24 -08003310static int in_stop(const struct audio_stream_in* stream)
3311{
3312 struct stream_in *in = (struct stream_in *)stream;
3313 struct audio_device *adev = in->dev;
3314
3315 int ret = -ENOSYS;
3316 ALOGV("%s", __func__);
3317 pthread_mutex_lock(&adev->lock);
3318 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3319 in->capture_started && in->pcm != NULL) {
3320 pcm_stop(in->pcm);
3321 ret = stop_input_stream(in);
Phil Burkbc991042017-02-24 08:06:44 -08003322 in->capture_started = false;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003323 }
3324 pthread_mutex_unlock(&adev->lock);
3325 return ret;
3326}
3327
3328static int in_start(const struct audio_stream_in* stream)
3329{
3330 struct stream_in *in = (struct stream_in *)stream;
3331 struct audio_device *adev = in->dev;
3332 int ret = -ENOSYS;
3333
3334 ALOGV("%s in %p", __func__, in);
3335 pthread_mutex_lock(&adev->lock);
3336 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
3337 !in->capture_started && in->pcm != NULL) {
3338 if (!in->capture_started) {
3339 ret = start_input_stream(in);
3340 if (ret == 0) {
3341 in->capture_started = true;
3342 }
3343 }
3344 }
3345 pthread_mutex_unlock(&adev->lock);
3346 return ret;
3347}
3348
3349static int in_create_mmap_buffer(const struct audio_stream_in *stream,
3350 int32_t min_size_frames,
3351 struct audio_mmap_buffer_info *info)
3352{
3353 struct stream_in *in = (struct stream_in *)stream;
3354 struct audio_device *adev = in->dev;
3355 int ret = 0;
3356 unsigned int offset1;
3357 unsigned int frames1;
3358 const char *step = "";
3359
3360 pthread_mutex_lock(&adev->lock);
3361 ALOGV("%s in %p", __func__, in);
Phil Burkbc991042017-02-24 08:06:44 -08003362
Eric Laurent0e46adf2016-12-16 12:49:24 -08003363 if (info == NULL || min_size_frames == 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003364 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003365 ret = -EINVAL;
3366 goto exit;
3367 }
3368 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
Phil Burkbc991042017-02-24 08:06:44 -08003369 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003370 ALOGV("%s in %p", __func__, in);
3371 ret = -ENOSYS;
3372 goto exit;
3373 }
3374 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
3375 if (in->pcm_device_id < 0) {
3376 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3377 __func__, in->pcm_device_id, in->usecase);
3378 ret = -EINVAL;
3379 goto exit;
3380 }
Phil Burkbc991042017-02-24 08:06:44 -08003381
3382 adjust_mmap_period_count(&in->config, min_size_frames);
3383
Eric Laurent0e46adf2016-12-16 12:49:24 -08003384 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3385 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3386 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
3387 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
3388 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3389 step = "open";
3390 ret = -ENODEV;
3391 goto exit;
3392 }
3393
3394 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
3395 if (ret < 0) {
3396 step = "begin";
3397 goto exit;
3398 }
3399 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
3400 info->burst_size_frames = in->config.period_size;
3401 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
3402
3403 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(in->pcm,
3404 info->buffer_size_frames));
3405
3406 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
3407 if (ret < 0) {
3408 step = "commit";
3409 goto exit;
3410 }
3411
Phil Burkbc991042017-02-24 08:06:44 -08003412 in->standby = false;
3413 ret = 0;
3414
Eric Laurent0e46adf2016-12-16 12:49:24 -08003415 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
3416 __func__, info->shared_memory_address, info->buffer_size_frames);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003417
3418exit:
3419 if (ret != 0) {
Phil Burkbc991042017-02-24 08:06:44 -08003420 if (in->pcm == NULL) {
3421 ALOGE("%s: %s - %d", __func__, step, ret);
3422 } else {
3423 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
Eric Laurent0e46adf2016-12-16 12:49:24 -08003424 pcm_close(in->pcm);
3425 in->pcm = NULL;
3426 }
3427 }
3428 pthread_mutex_unlock(&adev->lock);
3429 return ret;
3430}
3431
3432static int in_get_mmap_position(const struct audio_stream_in *stream,
3433 struct audio_mmap_position *position)
3434{
3435 struct stream_in *in = (struct stream_in *)stream;
3436 ALOGVV("%s", __func__);
3437 if (position == NULL) {
3438 return -EINVAL;
3439 }
3440 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
3441 return -ENOSYS;
3442 }
3443 if (in->pcm == NULL) {
3444 return -ENOSYS;
3445 }
3446 struct timespec ts = { 0, 0 };
3447 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
3448 if (ret < 0) {
3449 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3450 return ret;
3451 }
Andy Hungfc044e12017-03-20 09:24:22 -07003452 position->time_nanoseconds = audio_utils_ns_from_timespec(&ts);
Eric Laurent0e46adf2016-12-16 12:49:24 -08003453 return 0;
3454}
3455
3456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003457static int adev_open_output_stream(struct audio_hw_device *dev,
3458 audio_io_handle_t handle,
3459 audio_devices_t devices,
3460 audio_output_flags_t flags,
3461 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07003462 struct audio_stream_out **stream_out,
3463 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464{
3465 struct audio_device *adev = (struct audio_device *)dev;
3466 struct stream_out *out;
3467 int i, ret;
Haynes Mathew George569b7482017-05-08 14:44:27 -07003468 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
3469 bool is_usb_dev = audio_is_usb_out_device(devices) &&
3470 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
3471 bool direct_dev = is_hdmi || is_usb_dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472
Eric Laurent994a6932013-07-17 11:51:42 -07003473 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003474 __func__, config->sample_rate, config->channel_mask, devices, flags);
3475 *stream_out = NULL;
3476 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
3477
3478 if (devices == AUDIO_DEVICE_NONE)
3479 devices = AUDIO_DEVICE_OUT_SPEAKER;
3480
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003481 out->flags = flags;
3482 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07003483 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484 out->format = config->format;
3485 out->sample_rate = config->sample_rate;
3486 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
3487 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07003488 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489
3490 /* Init use case and pcm_config */
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003491 if (audio_is_linear_pcm(out->format) &&
3492 (out->flags == AUDIO_OUTPUT_FLAG_NONE ||
Haynes Mathew George569b7482017-05-08 14:44:27 -07003493 out->flags == AUDIO_OUTPUT_FLAG_DIRECT) && direct_dev) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003494 pthread_mutex_lock(&adev->lock);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003495 if (is_hdmi) {
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003496 ret = read_hdmi_channel_masks(out);
Haynes Mathew George569b7482017-05-08 14:44:27 -07003497 if (config->sample_rate == 0)
3498 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
3499 if (config->channel_mask == 0)
3500 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
3501 if (config->format == AUDIO_FORMAT_DEFAULT)
3502 config->format = AUDIO_FORMAT_PCM_16_BIT;
3503 } else if (is_usb_dev) {
3504 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
3505 &config->format,
3506 &out->supported_formats[0],
3507 MAX_SUPPORTED_FORMATS,
3508 &config->channel_mask,
3509 &out->supported_channel_masks[0],
3510 MAX_SUPPORTED_CHANNEL_MASKS,
3511 &config->sample_rate,
3512 &out->supported_sample_rates[0],
3513 MAX_SUPPORTED_SAMPLE_RATES);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003514 ALOGV("plugged dev USB ret %d", ret);
3515 } else {
3516 ret = -1;
3517 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003518 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07003519 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003520 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003521
Haynes Mathew George569b7482017-05-08 14:44:27 -07003522 out->channel_mask = config->channel_mask;
3523 out->sample_rate = config->sample_rate;
3524 out->format = config->format;
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003525 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
3526 // does this change?
Haynes Mathew George569b7482017-05-08 14:44:27 -07003527 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003529 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08003531 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003532 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew George35807692016-07-07 20:04:54 -07003533 pthread_mutex_lock(&adev->lock);
3534 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
3535 pthread_mutex_unlock(&adev->lock);
3536
3537 // reject offload during card offline to allow
3538 // fallback to s/w paths
3539 if (offline) {
3540 ret = -ENODEV;
3541 goto error_open;
3542 }
3543
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003544 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
3545 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
3546 ALOGE("%s: Unsupported Offload information", __func__);
3547 ret = -EINVAL;
3548 goto error_open;
3549 }
3550 if (!is_supported_format(config->offload_info.format)) {
3551 ALOGE("%s: Unsupported audio format", __func__);
3552 ret = -EINVAL;
3553 goto error_open;
3554 }
3555
3556 out->compr_config.codec = (struct snd_codec *)
3557 calloc(1, sizeof(struct snd_codec));
3558
3559 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
3560 if (config->offload_info.channel_mask)
3561 out->channel_mask = config->offload_info.channel_mask;
3562 else if (config->channel_mask)
3563 out->channel_mask = config->channel_mask;
3564 out->format = config->offload_info.format;
3565 out->sample_rate = config->offload_info.sample_rate;
3566
3567 out->stream.set_callback = out_set_callback;
3568 out->stream.pause = out_pause;
3569 out->stream.resume = out_resume;
3570 out->stream.drain = out_drain;
3571 out->stream.flush = out_flush;
3572
3573 out->compr_config.codec->id =
3574 get_snd_codec_id(config->offload_info.format);
3575 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
3576 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07003577 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003578 out->compr_config.codec->bit_rate =
3579 config->offload_info.bit_rate;
3580 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07003581 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003582 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
3583
3584 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
3585 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003586
3587 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003588 create_offload_callback_thread(out);
3589 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
3590 __func__, config->offload_info.version,
3591 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003592 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Kevin Rocard50eff892017-05-02 16:52:05 -07003593 switch (config->sample_rate) {
3594 case 8000:
3595 case 16000:
3596 case 48000:
3597 out->sample_rate = config->sample_rate;
3598 break;
3599 default:
3600 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003601 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003602 out->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003603 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
3604 out->config = pcm_config_afe_proxy_playback;
3605 adev->voice_tx_output = out;
vivek mehtaa68fea62017-06-08 19:04:02 -07003606 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3607 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT |
3608 AUDIO_OUTPUT_FLAG_VOIP_RX))) {
3609 uint32_t buffer_size, frame_size;
3610 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_MONO;
3611 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
3612 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
3613 out->config = pcm_config_voip;
3614 out->config.format = pcm_format_from_audio_format(config->format);
3615 out->config.rate = config->sample_rate;
3616 out->config.channels =
3617 audio_channel_count_from_out_mask(config->channel_mask);
3618 buffer_size = get_stream_buffer_size(VOIP_PLAYBACK_PERIOD_DURATION_MSEC,
3619 config->sample_rate,
3620 config->format,
3621 out->config.channels,
3622 false /*is_low_latency*/);
3623 frame_size = audio_bytes_per_sample(config->format) * out->config.channels;
3624 out->config.period_size = buffer_size / frame_size;
3625 out->config.period_count = VOIP_PLAYBACK_PERIOD_COUNT;
3626 out->af_period_multiplier = 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003627 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07003628 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3629 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3630 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07003631 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
3632 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
3633 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07003634 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3635 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003636 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
Haynes Mathew George03c40102016-01-29 17:57:48 -08003637 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003638 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
3639 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
3640 out->config = pcm_config_mmap_playback;
3641 out->stream.start = out_start;
3642 out->stream.stop = out_stop;
3643 out->stream.create_mmap_buffer = out_create_mmap_buffer;
3644 out->stream.get_mmap_position = out_get_mmap_position;
Andy Hung6fcba9c2014-03-18 11:53:32 -07003645 } else {
3646 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3647 out->config = pcm_config_low_latency;
3648 }
3649 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3650 if (k_enable_extended_precision
3651 && pcm_params_format_test(adev->use_case_table[out->usecase],
3652 pcm_format_from_audio_format(config->format))) {
3653 out->config.format = pcm_format_from_audio_format(config->format);
3654 /* out->format already set to config->format */
3655 } else {
3656 /* deny the externally proposed config format
3657 * and use the one specified in audio_hw layer configuration.
3658 * Note: out->format is returned by out->stream.common.get_format()
3659 * and is used to set config->format in the code several lines below.
3660 */
3661 out->format = audio_format_from_pcm_format(out->config.format);
3662 }
3663 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003664 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003665 }
Kevin Rocard50eff892017-05-02 16:52:05 -07003666
3667 if ((config->sample_rate != 0 && config->sample_rate != out->sample_rate) ||
3668 (config->format != AUDIO_FORMAT_DEFAULT && config->format != out->format) ||
3669 (config->channel_mask != 0 && config->channel_mask != out->channel_mask)) {
3670 ALOGI("%s: Unsupported output config. sample_rate:%u format:%#x channel_mask:%#x",
3671 __func__, config->sample_rate, config->format, config->channel_mask);
3672 config->sample_rate = out->sample_rate;
3673 config->format = out->format;
3674 config->channel_mask = out->channel_mask;
3675 ret = -EINVAL;
3676 goto error_open;
3677 }
3678
Andy Hung6fcba9c2014-03-18 11:53:32 -07003679 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
3680 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003682 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07003683 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003684 adev->primary_output = out;
3685 else {
3686 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003687 ret = -EEXIST;
3688 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003689 }
3690 }
3691
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003692 /* Check if this usecase is already existing */
3693 pthread_mutex_lock(&adev->lock);
3694 if (get_usecase_from_list(adev, out->usecase) != NULL) {
3695 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003696 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003697 ret = -EEXIST;
3698 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 }
3700 pthread_mutex_unlock(&adev->lock);
3701
3702 out->stream.common.get_sample_rate = out_get_sample_rate;
3703 out->stream.common.set_sample_rate = out_set_sample_rate;
3704 out->stream.common.get_buffer_size = out_get_buffer_size;
3705 out->stream.common.get_channels = out_get_channels;
3706 out->stream.common.get_format = out_get_format;
3707 out->stream.common.set_format = out_set_format;
3708 out->stream.common.standby = out_standby;
3709 out->stream.common.dump = out_dump;
3710 out->stream.common.set_parameters = out_set_parameters;
3711 out->stream.common.get_parameters = out_get_parameters;
3712 out->stream.common.add_audio_effect = out_add_audio_effect;
3713 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3714 out->stream.get_latency = out_get_latency;
3715 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003716#ifdef NO_AUDIO_OUT
3717 out->stream.write = out_write_for_no_output;
3718#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07003720#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 out->stream.get_render_position = out_get_render_position;
3722 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003723 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724
Eric Laurent0e46adf2016-12-16 12:49:24 -08003725 if (out->realtime)
3726 out->af_period_multiplier = af_period_multiplier;
3727 else
3728 out->af_period_multiplier = 1;
3729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003731 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003732 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003733
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003734 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07003735 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003736 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 config->format = out->stream.common.get_format(&out->stream.common);
3739 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3740 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3741
Andy Hunga452b0a2017-03-15 14:51:15 -07003742 out->error_log = error_log_create(
3743 ERROR_LOG_ENTRIES,
3744 1000000000 /* aggregate consecutive identical errors within one second in ns */);
3745
Andy Hungfc044e12017-03-20 09:24:22 -07003746 // power_log may be null if the format is not supported
Andy Hung9e737de2017-05-22 10:51:22 -07003747 // or not a userdebug or eng build.
Andy Hung02caae52017-06-06 12:33:33 -07003748 if (false /* is_userdebug_or_eng_build() */) {
Andy Hung9e737de2017-05-22 10:51:22 -07003749 const size_t POWER_LOG_FRAMES_PER_ENTRY =
3750 (long long)config->sample_rate * POWER_LOG_SAMPLING_INTERVAL_MS / 1000;
3751
3752 out->power_log = power_log_create(
3753 config->sample_rate,
3754 audio_channel_count_from_out_mask(config->channel_mask),
3755 config->format,
3756 POWER_LOG_ENTRIES,
3757 POWER_LOG_FRAMES_PER_ENTRY);
3758 }
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003759
3760 /*
3761 By locking output stream before registering, we allow the callback
3762 to update stream's state only after stream's initial state is set to
3763 adev state.
3764 */
3765 lock_output_stream(out);
3766 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
3767 pthread_mutex_lock(&adev->lock);
3768 out->card_status = adev->card_status;
3769 pthread_mutex_unlock(&adev->lock);
3770 pthread_mutex_unlock(&out->lock);
3771
vivek mehta4a824772017-06-08 19:05:49 -07003772 stream_app_type_cfg_init(&out->app_type_cfg);
3773
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774 *stream_out = &out->stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08003775
Eric Laurent994a6932013-07-17 11:51:42 -07003776 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003778
3779error_open:
3780 free(out);
3781 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07003782 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003783 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003784}
3785
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003786static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003787 struct audio_stream_out *stream)
3788{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003789 struct stream_out *out = (struct stream_out *)stream;
3790 struct audio_device *adev = out->dev;
3791
Eric Laurent994a6932013-07-17 11:51:42 -07003792 ALOGV("%s: enter", __func__);
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07003793
3794 // must deregister from sndmonitor first to prevent races
3795 // between the callback and close_stream
3796 audio_extn_snd_mon_unregister_listener(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003797 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003798 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
3799 destroy_offload_callback_thread(out);
3800
3801 if (out->compr_config.codec != NULL)
3802 free(out->compr_config.codec);
3803 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07003804
3805 if (adev->voice_tx_output == out)
3806 adev->voice_tx_output = NULL;
3807
Andy Hungfc044e12017-03-20 09:24:22 -07003808 power_log_destroy(out->power_log);
3809 out->power_log = NULL;
3810
Andy Hunga452b0a2017-03-15 14:51:15 -07003811 error_log_destroy(out->error_log);
3812 out->error_log = NULL;
3813
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003814 pthread_cond_destroy(&out->cond);
3815 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003817 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003818}
3819
3820static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3821{
3822 struct audio_device *adev = (struct audio_device *)dev;
3823 struct str_parms *parms;
3824 char *str;
3825 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003826 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003827 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07003828 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829
Joe Onorato188b6222016-03-01 11:02:27 -08003830 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003831
3832 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003833
3834 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003835 status = voice_set_parameters(adev, parms);
3836 if (status != 0) {
3837 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 }
3839
3840 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3841 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07003842 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003843 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3844 adev->bluetooth_nrec = true;
3845 else
3846 adev->bluetooth_nrec = false;
3847 }
3848
3849 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3850 if (ret >= 0) {
3851 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3852 adev->screen_off = false;
3853 else
3854 adev->screen_off = true;
3855 }
3856
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003857 ret = str_parms_get_int(parms, "rotation", &val);
3858 if (ret >= 0) {
3859 bool reverse_speakers = false;
3860 switch(val) {
3861 // FIXME: note that the code below assumes that the speakers are in the correct placement
3862 // relative to the user when the device is rotated 90deg from its default rotation. This
3863 // assumption is device-specific, not platform-specific like this code.
3864 case 270:
3865 reverse_speakers = true;
3866 break;
3867 case 0:
3868 case 90:
3869 case 180:
3870 break;
3871 default:
3872 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07003873 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003874 }
Eric Laurent03f09432014-03-25 18:09:11 -07003875 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07003876 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003877 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003878 }
3879
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003880 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
3881 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003882 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003883 }
3884
David Linee3fe402017-03-13 10:00:42 -07003885 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
3886 if (ret >= 0) {
3887 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003888 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003889 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3890 if (ret >= 0) {
3891 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003892 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003893 }
Eric Laurent99dab492017-06-17 15:19:08 -07003894 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003895 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3896 if (ret >= 0) {
3897 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003898 audio_extn_usb_add_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003899 }
3900 }
3901 }
3902
3903 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
3904 if (ret >= 0) {
3905 audio_devices_t device = (audio_devices_t)strtoul(value, NULL, 10);
Eric Laurent99dab492017-06-17 15:19:08 -07003906 if (audio_is_usb_out_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003907 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3908 if (ret >= 0) {
3909 const int card = atoi(value);
3910
Eric Laurent99dab492017-06-17 15:19:08 -07003911 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003912 }
Eric Laurent99dab492017-06-17 15:19:08 -07003913 } else if (audio_is_usb_in_device(device)) {
David Linee3fe402017-03-13 10:00:42 -07003914 ret = str_parms_get_str(parms, "card", value, sizeof(value));
3915 if (ret >= 0) {
3916 const int card = atoi(value);
Eric Laurent99dab492017-06-17 15:19:08 -07003917 audio_extn_usb_remove_device(device, card);
David Linee3fe402017-03-13 10:00:42 -07003918 }
3919 }
3920 }
3921
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08003922 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003923done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003924 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003925 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07003926 ALOGV("%s: exit with code(%d)", __func__, status);
3927 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928}
3929
3930static char* adev_get_parameters(const struct audio_hw_device *dev,
3931 const char *keys)
3932{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003933 struct audio_device *adev = (struct audio_device *)dev;
3934 struct str_parms *reply = str_parms_create();
3935 struct str_parms *query = str_parms_create_str(keys);
3936 char *str;
3937
3938 pthread_mutex_lock(&adev->lock);
3939
3940 voice_get_parameters(adev, query, reply);
3941 str = str_parms_to_str(reply);
3942 str_parms_destroy(query);
3943 str_parms_destroy(reply);
3944
3945 pthread_mutex_unlock(&adev->lock);
3946 ALOGV("%s: exit: returns - %s", __func__, str);
3947 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003948}
3949
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003950static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951{
3952 return 0;
3953}
3954
Haynes Mathew George5191a852013-09-11 14:19:36 -07003955static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3956{
3957 int ret;
3958 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003959
Eric Laurent4cc4ce12014-09-10 13:21:01 -05003960 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3961
Haynes Mathew George5191a852013-09-11 14:19:36 -07003962 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003963 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003964 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003965
Haynes Mathew George5191a852013-09-11 14:19:36 -07003966 return ret;
3967}
3968
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003969static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970{
3971 return -ENOSYS;
3972}
3973
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003974static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3975 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003976{
3977 return -ENOSYS;
3978}
3979
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003980static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003981{
3982 return -ENOSYS;
3983}
3984
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003985static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986{
3987 return -ENOSYS;
3988}
3989
3990static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3991{
3992 struct audio_device *adev = (struct audio_device *)dev;
3993
3994 pthread_mutex_lock(&adev->lock);
3995 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07003996 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003997 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07003998 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
3999 voice_is_in_call(adev)) {
4000 voice_stop_call(adev);
4001 adev->current_call_output = NULL;
4002 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004003 }
4004 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004005
4006 audio_extn_extspk_set_mode(adev->extspk, mode);
4007
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004008 return 0;
4009}
4010
4011static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
4012{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004013 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004014 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004015
Eric Laurent2bafff12016-03-17 12:17:23 -07004016 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004017 pthread_mutex_lock(&adev->lock);
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004018 if (audio_extn_tfa_98xx_is_supported() && adev->enable_hfp) {
4019 ret = audio_extn_hfp_set_mic_mute(adev, state);
4020 } else {
4021 ret = voice_set_mic_mute(adev, state);
4022 }
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07004023 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00004024 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004025
4026 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004027}
4028
4029static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
4030{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004031 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032 return 0;
4033}
4034
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004035static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004036 const struct audio_config *config)
4037{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004038 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004039
vivek mehtaa68fea62017-06-08 19:04:02 -07004040 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4041 config->sample_rate, config->format,
4042 channel_count,
4043 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004044}
4045
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004046static bool adev_input_allow_hifi_record(struct audio_device *adev,
4047 audio_devices_t devices,
4048 audio_input_flags_t flags,
4049 audio_source_t source) {
4050 const bool allowed = true;
4051
4052 if (!audio_is_usb_in_device(devices))
4053 return !allowed;
4054
4055 switch (flags) {
4056 case AUDIO_INPUT_FLAG_NONE:
4057 case AUDIO_INPUT_FLAG_FAST: // just fast, not fast|raw || fast|mmap
4058 break;
4059 default:
4060 return !allowed;
4061 }
4062
4063 switch (source) {
4064 case AUDIO_SOURCE_DEFAULT:
4065 case AUDIO_SOURCE_MIC:
4066 case AUDIO_SOURCE_UNPROCESSED:
4067 break;
4068 default:
4069 return !allowed;
4070 }
4071
4072 switch (adev->mode) {
4073 case 0:
4074 break;
4075 default:
4076 return !allowed;
4077 }
4078
4079 return allowed;
4080}
4081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004082static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004083 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004084 audio_devices_t devices,
4085 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004086 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07004087 audio_input_flags_t flags,
4088 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05004089 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004090{
4091 struct audio_device *adev = (struct audio_device *)dev;
4092 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004093 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07004094 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004095 bool is_low_latency = false;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004096 bool is_usb_dev = audio_is_usb_in_device(devices);
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004097 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
4098 devices,
4099 flags,
4100 source);
4101 ALOGE("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004102 *stream_in = NULL;
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004103
4104 if (config->sample_rate == 0)
4105 config->sample_rate = DEFAULT_INPUT_SAMPLING_RATE;
4106 if (config->channel_mask == AUDIO_CHANNEL_NONE)
4107 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
4108 if (config->format == AUDIO_FORMAT_DEFAULT)
4109 config->format = AUDIO_FORMAT_PCM_16_BIT;
4110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004111 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
4112 return -EINVAL;
4113
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004114 if (audio_extn_tfa_98xx_is_supported() &&
4115 (audio_extn_hfp_is_active(adev) || voice_is_in_call(adev)))
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004116 return -EINVAL;
4117
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
4119
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004120 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07004121 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004122
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004123 in->stream.common.get_sample_rate = in_get_sample_rate;
4124 in->stream.common.set_sample_rate = in_set_sample_rate;
4125 in->stream.common.get_buffer_size = in_get_buffer_size;
4126 in->stream.common.get_channels = in_get_channels;
4127 in->stream.common.get_format = in_get_format;
4128 in->stream.common.set_format = in_set_format;
4129 in->stream.common.standby = in_standby;
4130 in->stream.common.dump = in_dump;
4131 in->stream.common.set_parameters = in_set_parameters;
4132 in->stream.common.get_parameters = in_get_parameters;
4133 in->stream.common.add_audio_effect = in_add_audio_effect;
4134 in->stream.common.remove_audio_effect = in_remove_audio_effect;
4135 in->stream.set_gain = in_set_gain;
4136 in->stream.read = in_read;
4137 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08004138 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004139
4140 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004141 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004142 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 in->standby = 1;
4144 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004145 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004146 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004147
Haynes Mathew George569b7482017-05-08 14:44:27 -07004148 if (is_usb_dev && may_use_hifi_record) {
4149 /* HiFi record selects an appropriate format, channel, rate combo
4150 depending on sink capabilities*/
4151 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
4152 &config->format,
4153 &in->supported_formats[0],
4154 MAX_SUPPORTED_FORMATS,
4155 &config->channel_mask,
4156 &in->supported_channel_masks[0],
4157 MAX_SUPPORTED_CHANNEL_MASKS,
4158 &config->sample_rate,
4159 &in->supported_sample_rates[0],
4160 MAX_SUPPORTED_SAMPLE_RATES);
4161 if (ret != 0) {
4162 ret = -EINVAL;
4163 goto err_open;
4164 }
4165 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07004166 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07004167 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
4168 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
4169 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
4170 bool ret_error = false;
4171 /* 24 bit is restricted to UNPROCESSED source only,also format supported
4172 from HAL is 8_24
4173 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
4174 8_24 return error indicating supported format is 8_24
4175 *> In case of any other source requesting 24 bit or float return error
4176 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07004177
vivek mehta57ff9b52016-04-28 14:13:08 -07004178 on error flinger will retry with supported format passed
4179 */
4180 if (source != AUDIO_SOURCE_UNPROCESSED) {
4181 config->format = AUDIO_FORMAT_PCM_16_BIT;
4182 ret_error = true;
4183 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
4184 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
4185 ret_error = true;
4186 }
4187
4188 if (ret_error) {
4189 ret = -EINVAL;
4190 goto err_open;
4191 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004192 }
4193
vivek mehta57ff9b52016-04-28 14:13:08 -07004194 in->format = config->format;
4195
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004197 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
4198 if (config->sample_rate == 0)
4199 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4200 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
4201 config->sample_rate != 8000) {
4202 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
4203 ret = -EINVAL;
4204 goto err_open;
4205 }
vivek mehta4ed66e62016-04-15 23:33:34 -07004206
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004207 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
4208 config->format = AUDIO_FORMAT_PCM_16_BIT;
4209 ret = -EINVAL;
4210 goto err_open;
4211 }
4212
4213 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
4214 in->config = pcm_config_afe_proxy_record;
David Line5b12ac2017-03-29 13:37:33 -07004215 in->af_period_multiplier = 1;
Haynes Mathew George569b7482017-05-08 14:44:27 -07004216 } else if (is_usb_dev && may_use_hifi_record) {
4217 in->usecase = USECASE_AUDIO_RECORD_HIFI;
4218 in->config = pcm_config_audio_capture;
4219 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004220 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4221 config->sample_rate,
4222 config->format,
4223 channel_count,
4224 false /*is_low_latency*/);
Haynes Mathew George569b7482017-05-08 14:44:27 -07004225 in->config.period_size = buffer_size / frame_size;
4226 in->config.rate = config->sample_rate;
4227 in->af_period_multiplier = 1;
4228 in->config.format = pcm_format_from_audio_format(config->format);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004229 } else {
4230 in->usecase = USECASE_AUDIO_RECORD;
4231 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Eric Laurent0e46adf2016-12-16 12:49:24 -08004232 (in->flags & AUDIO_INPUT_FLAG_FAST) != 0) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004233 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07004234#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07004235 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07004236#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08004237 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004238 if (!in->realtime) {
Eric Laurentff1e5e62017-02-21 16:08:55 -08004239 in->config = pcm_config_audio_capture;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004240 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004241 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4242 config->sample_rate,
4243 config->format,
4244 channel_count,
4245 is_low_latency);
Eric Laurent0e46adf2016-12-16 12:49:24 -08004246 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004247 in->config.rate = config->sample_rate;
4248 in->af_period_multiplier = 1;
4249 } else {
4250 // period size is left untouched for rt mode playback
4251 in->config = pcm_config_audio_capture_rt;
4252 in->af_period_multiplier = af_period_multiplier;
4253 }
4254 } else if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
4255 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
Haynes Mathew Georgee95340e2017-05-24 15:42:06 -07004256 // FIXME: Add support for multichannel capture over USB using MMAP
Eric Laurent0e46adf2016-12-16 12:49:24 -08004257 in->usecase = USECASE_AUDIO_RECORD_MMAP;
4258 in->config = pcm_config_mmap_capture;
4259 in->stream.start = in_start;
4260 in->stream.stop = in_stop;
4261 in->stream.create_mmap_buffer = in_create_mmap_buffer;
4262 in->stream.get_mmap_position = in_get_mmap_position;
4263 in->af_period_multiplier = 1;
4264 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
vivek mehtaa68fea62017-06-08 19:04:02 -07004265 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
4266 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION &&
vivek mehta4a824772017-06-08 19:05:49 -07004267 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
vivek mehtaa68fea62017-06-08 19:04:02 -07004268 (config->sample_rate == 8000 ||
4269 config->sample_rate == 16000 ||
4270 config->sample_rate == 32000 ||
4271 config->sample_rate == 48000) &&
4272 channel_count == 1) {
4273 in->usecase = USECASE_AUDIO_RECORD_VOIP;
4274 in->config = pcm_config_audio_capture;
4275 frame_size = audio_stream_in_frame_size(&in->stream);
4276 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
4277 config->sample_rate,
4278 config->format,
4279 channel_count, false /*is_low_latency*/);
4280 in->config.period_size = buffer_size / frame_size;
4281 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
4282 in->config.rate = config->sample_rate;
4283 in->af_period_multiplier = 1;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004284 } else {
4285 in->config = pcm_config_audio_capture;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004286 frame_size = audio_stream_in_frame_size(&in->stream);
vivek mehtaa68fea62017-06-08 19:04:02 -07004287 buffer_size = get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4288 config->sample_rate,
4289 config->format,
4290 channel_count,
4291 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08004292 in->config.period_size = buffer_size / frame_size;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004293 in->config.rate = config->sample_rate;
4294 in->af_period_multiplier = 1;
4295 }
4296 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
4297 in->config.format = PCM_FORMAT_S24_LE;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07004298 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08004299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004300 in->config.channels = channel_count;
vivek mehtaa68fea62017-06-08 19:04:02 -07004301 in->sample_rate = in->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004302
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004303 /* This stream could be for sound trigger lab,
4304 get sound trigger pcm if present */
4305 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004306
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004307 lock_input_stream(in);
4308 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
4309 pthread_mutex_lock(&adev->lock);
4310 in->card_status = adev->card_status;
4311 pthread_mutex_unlock(&adev->lock);
4312 pthread_mutex_unlock(&in->lock);
4313
vivek mehta4a824772017-06-08 19:05:49 -07004314 stream_app_type_cfg_init(&in->app_type_cfg);
4315
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004316 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07004317 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318 return 0;
4319
4320err_open:
4321 free(in);
4322 *stream_in = NULL;
4323 return ret;
4324}
4325
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004326static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327 struct audio_stream_in *stream)
4328{
Eric Laurent994a6932013-07-17 11:51:42 -07004329 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004330
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004331 // must deregister from sndmonitor first to prevent races
4332 // between the callback and close_stream
4333 audio_extn_snd_mon_unregister_listener(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004334 in_standby(&stream->common);
4335 free(stream);
4336
4337 return;
4338}
4339
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07004340static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004341{
4342 return 0;
4343}
4344
Andy Hung31aca912014-03-20 17:14:59 -07004345/* verifies input and output devices and their capabilities.
4346 *
4347 * This verification is required when enabling extended bit-depth or
4348 * sampling rates, as not all qcom products support it.
4349 *
4350 * Suitable for calling only on initialization such as adev_open().
4351 * It fills the audio_device use_case_table[] array.
4352 *
4353 * Has a side-effect that it needs to configure audio routing / devices
4354 * in order to power up the devices and read the device parameters.
4355 * It does not acquire any hw device lock. Should restore the devices
4356 * back to "normal state" upon completion.
4357 */
4358static int adev_verify_devices(struct audio_device *adev)
4359{
4360 /* enumeration is a bit difficult because one really wants to pull
4361 * the use_case, device id, etc from the hidden pcm_device_table[].
4362 * In this case there are the following use cases and device ids.
4363 *
4364 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
4365 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004366 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
Andy Hung31aca912014-03-20 17:14:59 -07004367 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
4368 * [USECASE_AUDIO_RECORD] = {0, 0},
4369 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
4370 * [USECASE_VOICE_CALL] = {2, 2},
4371 *
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004372 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
Andy Hung31aca912014-03-20 17:14:59 -07004373 * USECASE_VOICE_CALL omitted, but possible for either input or output.
4374 */
4375
4376 /* should be the usecases enabled in adev_open_input_stream() */
4377 static const int test_in_usecases[] = {
4378 USECASE_AUDIO_RECORD,
4379 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
4380 };
4381 /* should be the usecases enabled in adev_open_output_stream()*/
4382 static const int test_out_usecases[] = {
4383 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
4384 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
4385 };
4386 static const usecase_type_t usecase_type_by_dir[] = {
4387 PCM_PLAYBACK,
4388 PCM_CAPTURE,
4389 };
4390 static const unsigned flags_by_dir[] = {
4391 PCM_OUT,
4392 PCM_IN,
4393 };
4394
4395 size_t i;
4396 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004397 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07004398 char info[512]; /* for possible debug info */
4399
4400 for (dir = 0; dir < 2; ++dir) {
4401 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
4402 const unsigned flags_dir = flags_by_dir[dir];
4403 const size_t testsize =
4404 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
4405 const int *testcases =
4406 dir ? test_in_usecases : test_out_usecases;
4407 const audio_devices_t audio_device =
4408 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
4409
4410 for (i = 0; i < testsize; ++i) {
4411 const audio_usecase_t audio_usecase = testcases[i];
4412 int device_id;
4413 snd_device_t snd_device;
4414 struct pcm_params **pparams;
4415 struct stream_out out;
4416 struct stream_in in;
4417 struct audio_usecase uc_info;
4418 int retval;
4419
4420 pparams = &adev->use_case_table[audio_usecase];
4421 pcm_params_free(*pparams); /* can accept null input */
4422 *pparams = NULL;
4423
4424 /* find the device ID for the use case (signed, for error) */
4425 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
4426 if (device_id < 0)
4427 continue;
4428
4429 /* prepare structures for device probing */
4430 memset(&uc_info, 0, sizeof(uc_info));
4431 uc_info.id = audio_usecase;
4432 uc_info.type = usecase_type;
4433 if (dir) {
4434 adev->active_input = &in;
4435 memset(&in, 0, sizeof(in));
4436 in.device = audio_device;
4437 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
4438 uc_info.stream.in = &in;
4439 } else {
4440 adev->active_input = NULL;
4441 }
4442 memset(&out, 0, sizeof(out));
4443 out.devices = audio_device; /* only field needed in select_devices */
4444 uc_info.stream.out = &out;
4445 uc_info.devices = audio_device;
4446 uc_info.in_snd_device = SND_DEVICE_NONE;
4447 uc_info.out_snd_device = SND_DEVICE_NONE;
4448 list_add_tail(&adev->usecase_list, &uc_info.list);
4449
4450 /* select device - similar to start_(in/out)put_stream() */
4451 retval = select_devices(adev, audio_usecase);
4452 if (retval >= 0) {
4453 *pparams = pcm_params_get(card_id, device_id, flags_dir);
4454#if LOG_NDEBUG == 0
4455 if (*pparams) {
4456 ALOGV("%s: (%s) card %d device %d", __func__,
4457 dir ? "input" : "output", card_id, device_id);
4458 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07004459 } else {
4460 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
4461 }
4462#endif
4463 }
4464
4465 /* deselect device - similar to stop_(in/out)put_stream() */
4466 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07004467 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07004468 /* 2. Disable the rx device */
4469 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07004470 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07004471 list_remove(&uc_info.list);
4472 }
4473 }
4474 adev->active_input = NULL; /* restore adev state */
4475 return 0;
4476}
4477
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004478static int adev_close(hw_device_t *device)
4479{
Andy Hung31aca912014-03-20 17:14:59 -07004480 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004481 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004482
4483 if (!adev)
4484 return 0;
4485
Kevin Rocarda5453442017-05-02 15:09:20 -07004486 audio_extn_snd_mon_unregister_listener(adev);
Kevin Rocard8342c2c2017-04-07 18:50:00 -07004487 audio_extn_snd_mon_deinit();
Kevin Rocarda5453442017-05-02 15:09:20 -07004488
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004489 audio_extn_tfa_98xx_deinit();
4490
vivek mehta1a9b7c02015-06-25 11:49:38 -07004491 pthread_mutex_lock(&adev_init_lock);
4492
4493 if ((--audio_device_ref_count) == 0) {
4494 audio_route_free(adev->audio_route);
4495 free(adev->snd_dev_ref_cnt);
4496 platform_deinit(adev->platform);
4497 audio_extn_extspk_deinit(adev->extspk);
4498 audio_extn_sound_trigger_deinit(adev);
4499 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
4500 pcm_params_free(adev->use_case_table[i]);
4501 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004502 if (adev->adm_deinit)
4503 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004504 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07004505 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07004506
4507 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004508
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004509 return 0;
4510}
4511
Glenn Kasten4f993392014-05-14 07:30:48 -07004512/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
4513 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
4514 * just that it _might_ work.
4515 */
4516static int period_size_is_plausible_for_low_latency(int period_size)
4517{
4518 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004519 case 48:
4520 case 96:
4521 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07004522 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07004523 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07004524 case 240:
4525 case 320:
4526 case 480:
4527 return 1;
4528 default:
4529 return 0;
4530 }
4531}
4532
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004533static void adev_snd_mon_cb(void * stream __unused, struct str_parms * parms)
4534{
4535 int card;
4536 card_status_t status;
4537
4538 if (!parms)
4539 return;
4540
4541 if (parse_snd_card_status(parms, &card, &status) < 0)
4542 return;
4543
4544 pthread_mutex_lock(&adev->lock);
4545 bool valid_cb = (card == adev->snd_card);
4546 if (valid_cb) {
4547 if (adev->card_status != status) {
4548 adev->card_status = status;
4549 platform_snd_card_update(adev->platform, status);
4550 }
4551 }
4552 pthread_mutex_unlock(&adev->lock);
4553 return;
4554}
4555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004556static int adev_open(const hw_module_t *module, const char *name,
4557 hw_device_t **device)
4558{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004559 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004560
Eric Laurent2bafff12016-03-17 12:17:23 -07004561 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004562 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004563 pthread_mutex_lock(&adev_init_lock);
4564 if (audio_device_ref_count != 0) {
4565 *device = &adev->device.common;
4566 audio_device_ref_count++;
4567 ALOGV("%s: returning existing instance of adev", __func__);
4568 ALOGV("%s: exit", __func__);
4569 pthread_mutex_unlock(&adev_init_lock);
4570 return 0;
4571 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004572 adev = calloc(1, sizeof(struct audio_device));
4573
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004574 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
4575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004576 adev->device.common.tag = HARDWARE_DEVICE_TAG;
4577 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
4578 adev->device.common.module = (struct hw_module_t *)module;
4579 adev->device.common.close = adev_close;
4580
4581 adev->device.init_check = adev_init_check;
4582 adev->device.set_voice_volume = adev_set_voice_volume;
4583 adev->device.set_master_volume = adev_set_master_volume;
4584 adev->device.get_master_volume = adev_get_master_volume;
4585 adev->device.set_master_mute = adev_set_master_mute;
4586 adev->device.get_master_mute = adev_get_master_mute;
4587 adev->device.set_mode = adev_set_mode;
4588 adev->device.set_mic_mute = adev_set_mic_mute;
4589 adev->device.get_mic_mute = adev_get_mic_mute;
4590 adev->device.set_parameters = adev_set_parameters;
4591 adev->device.get_parameters = adev_get_parameters;
4592 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
4593 adev->device.open_output_stream = adev_open_output_stream;
4594 adev->device.close_output_stream = adev_close_output_stream;
4595 adev->device.open_input_stream = adev_open_input_stream;
Eric Laurent0e46adf2016-12-16 12:49:24 -08004596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004597 adev->device.close_input_stream = adev_close_input_stream;
4598 adev->device.dump = adev_dump;
4599
4600 /* Set the default route before the PCM stream is opened */
4601 pthread_mutex_lock(&adev->lock);
4602 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08004603 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004604 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004605 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08004606 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07004607 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07004608 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07004609 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08004610 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004611 pthread_mutex_unlock(&adev->lock);
4612
4613 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07004614 adev->platform = platform_init(adev);
4615 if (!adev->platform) {
4616 free(adev->snd_dev_ref_cnt);
4617 free(adev);
4618 ALOGE("%s: Failed to init platform data, aborting.", __func__);
4619 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004620 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07004621 return -EINVAL;
4622 }
Eric Laurent0499d4f2014-08-25 22:39:29 -05004623 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07004624 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05004625
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004626 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
4627 if (adev->visualizer_lib == NULL) {
4628 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
4629 } else {
4630 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
4631 adev->visualizer_start_output =
4632 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4633 "visualizer_hal_start_output");
4634 adev->visualizer_stop_output =
4635 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
4636 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07004637 }
4638
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004639 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
4640 if (adev->offload_effects_lib == NULL) {
4641 ALOGW("%s: DLOPEN failed for %s", __func__,
4642 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4643 } else {
4644 ALOGV("%s: DLOPEN successful for %s", __func__,
4645 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
4646 adev->offload_effects_start_output =
4647 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4648 "offload_effects_bundle_hal_start_output");
4649 adev->offload_effects_stop_output =
4650 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
4651 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07004652 }
4653
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07004654 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
4655 if (adev->adm_lib == NULL) {
4656 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
4657 } else {
4658 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
4659 adev->adm_init = (adm_init_t)
4660 dlsym(adev->adm_lib, "adm_init");
4661 adev->adm_deinit = (adm_deinit_t)
4662 dlsym(adev->adm_lib, "adm_deinit");
4663 adev->adm_register_input_stream = (adm_register_input_stream_t)
4664 dlsym(adev->adm_lib, "adm_register_input_stream");
4665 adev->adm_register_output_stream = (adm_register_output_stream_t)
4666 dlsym(adev->adm_lib, "adm_register_output_stream");
4667 adev->adm_deregister_stream = (adm_deregister_stream_t)
4668 dlsym(adev->adm_lib, "adm_deregister_stream");
4669 adev->adm_request_focus = (adm_request_focus_t)
4670 dlsym(adev->adm_lib, "adm_request_focus");
4671 adev->adm_abandon_focus = (adm_abandon_focus_t)
4672 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08004673 adev->adm_set_config = (adm_set_config_t)
4674 dlsym(adev->adm_lib, "adm_set_config");
4675 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
4676 dlsym(adev->adm_lib, "adm_request_focus_v2");
4677 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
4678 dlsym(adev->adm_lib, "adm_is_noirq_avail");
4679 adev->adm_on_routing_change = (adm_on_routing_change_t)
4680 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004681 }
4682
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004683 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05004684 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07004685
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004686 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07004687
Andy Hung31aca912014-03-20 17:14:59 -07004688 if (k_enable_extended_precision)
4689 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004690
Glenn Kasten4f993392014-05-14 07:30:48 -07004691 char value[PROPERTY_VALUE_MAX];
4692 int trial;
4693 if (property_get("audio_hal.period_size", value, NULL) > 0) {
4694 trial = atoi(value);
4695 if (period_size_is_plausible_for_low_latency(trial)) {
4696 pcm_config_low_latency.period_size = trial;
4697 pcm_config_low_latency.start_threshold = trial / 4;
4698 pcm_config_low_latency.avail_min = trial / 4;
4699 configured_low_latency_capture_period_size = trial;
4700 }
4701 }
4702 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
4703 trial = atoi(value);
4704 if (period_size_is_plausible_for_low_latency(trial)) {
4705 configured_low_latency_capture_period_size = trial;
4706 }
4707 }
4708
Haynes Mathew Georgee5ff0fc2017-02-16 20:33:38 -08004709 // commented as full set of app type cfg is sent from platform
4710 // audio_extn_utils_send_default_app_type_cfg(adev->platform, adev->mixer);
vivek mehta1a9b7c02015-06-25 11:49:38 -07004711 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08004712
4713 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
4714 af_period_multiplier = atoi(value);
4715 if (af_period_multiplier < 0) {
4716 af_period_multiplier = 2;
4717 } else if (af_period_multiplier > 4) {
4718 af_period_multiplier = 4;
4719 }
4720 ALOGV("new period_multiplier = %d", af_period_multiplier);
4721 }
4722
Alain Vongsouvanh13f26e82016-11-18 14:39:11 -08004723 audio_extn_tfa_98xx_init(adev);
4724
vivek mehta1a9b7c02015-06-25 11:49:38 -07004725 pthread_mutex_unlock(&adev_init_lock);
4726
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07004727 if (adev->adm_init)
4728 adev->adm_data = adev->adm_init();
4729
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004730 audio_extn_perf_lock_init();
Haynes Mathew Georgec735fb02016-06-30 18:00:28 -07004731 audio_extn_snd_mon_init();
4732 pthread_mutex_lock(&adev->lock);
4733 audio_extn_snd_mon_register_listener(NULL, adev_snd_mon_cb);
4734 adev->card_status = CARD_STATUS_ONLINE;
4735 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07004736
Eric Laurent2bafff12016-03-17 12:17:23 -07004737 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004738 return 0;
4739}
4740
4741static struct hw_module_methods_t hal_module_methods = {
4742 .open = adev_open,
4743};
4744
4745struct audio_module HAL_MODULE_INFO_SYM = {
4746 .common = {
4747 .tag = HARDWARE_MODULE_TAG,
4748 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
4749 .hal_api_version = HARDWARE_HAL_API_VERSION,
4750 .id = AUDIO_HARDWARE_MODULE_ID,
4751 .name = "QCOM Audio HAL",
4752 .author = "Code Aurora Forum",
4753 .methods = &hal_module_methods,
4754 },
4755};