blob: 2a95ab84cdf21ca2175887a9ae6c00190e213e17 [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>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036
37#include <cutils/log.h>
Haynes Mathew George03c40102016-01-29 17:57:48 -080038#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080039#include <cutils/str_parms.h>
40#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041#include <cutils/atomic.h>
42#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Andy Hung31aca912014-03-20 17:14:59 -070045#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070047#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080049#include "audio_hw.h"
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -080050#include "audio_extn.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070051#include "platform_api.h"
52#include <platform.h>
Vineeta Srivastava4b89e372014-06-19 14:21:42 -070053#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include "sound/compress_params.h"
56
Eric Laurent397db572016-05-11 11:31:47 -070057/* COMPRESS_OFFLOAD_FRAGMENT_SIZE must be more than 8KB and a multiple of 32KB if more than 32KB.
58 * COMPRESS_OFFLOAD_FRAGMENT_SIZE * COMPRESS_OFFLOAD_NUM_FRAGMENTS must be less than 8MB. */
Marco Nelissen32093f52015-04-08 15:14:02 -070059#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070060// 2 buffers causes problems with high bitrate files
61#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062/* ToDo: Check and update a proper value in msec */
63#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
64#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
65
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070066#define PROXY_OPEN_RETRY_COUNT 100
67#define PROXY_OPEN_WAIT_TIME 20
68
vivek mehtadae44712015-07-27 14:13:18 -070069#define MIN_CHANNEL_COUNT 1
70#define DEFAULT_CHANNEL_COUNT 2
71
Jean-Michel Trivic0750692015-10-12 12:12:32 -070072#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
73#define MAX_CHANNEL_COUNT 1
74#else
vivek mehtadae44712015-07-27 14:13:18 -070075#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
76#define XSTR(x) STR(x)
77#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070078#endif
vivek mehtadae44712015-07-27 14:13:18 -070079
Haynes Mathew George03c40102016-01-29 17:57:48 -080080#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
81
Glenn Kasten4f993392014-05-14 07:30:48 -070082static unsigned int configured_low_latency_capture_period_size =
83 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
84
Andy Hung31aca912014-03-20 17:14:59 -070085/* This constant enables extended precision handling.
86 * TODO The flag is off until more testing is done.
87 */
88static const bool k_enable_extended_precision = false;
89
Eric Laurentb23d5282013-05-14 15:27:20 -070090struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -070091 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -070092 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
93 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
94 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
95 .format = PCM_FORMAT_S16_LE,
96 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
97 .stop_threshold = INT_MAX,
98 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
99};
100
101struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700102 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700103 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
104 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
105 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
108 .stop_threshold = INT_MAX,
109 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
110};
111
Haynes Mathew George03c40102016-01-29 17:57:48 -0800112static int af_period_multiplier = 4;
113struct pcm_config pcm_config_rt = {
114 .channels = DEFAULT_CHANNEL_COUNT,
115 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
116 .period_size = ULL_PERIOD_SIZE, //1 ms
117 .period_count = 512, //=> buffer size is 512ms
118 .format = PCM_FORMAT_S16_LE,
119 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
120 .stop_threshold = INT_MAX,
121 .silence_threshold = 0,
122 .silence_size = 0,
123 .avail_min = ULL_PERIOD_SIZE, //1 ms
124};
125
Eric Laurentb23d5282013-05-14 15:27:20 -0700126struct pcm_config pcm_config_hdmi_multi = {
127 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
128 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
129 .period_size = HDMI_MULTI_PERIOD_SIZE,
130 .period_count = HDMI_MULTI_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = 0,
133 .stop_threshold = INT_MAX,
134 .avail_min = 0,
135};
136
137struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700138 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700139 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
140 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700141 .stop_threshold = INT_MAX,
142 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700143};
144
Haynes Mathew George03c40102016-01-29 17:57:48 -0800145struct pcm_config pcm_config_audio_capture_rt = {
146 .channels = DEFAULT_CHANNEL_COUNT,
147 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
148 .period_size = ULL_PERIOD_SIZE,
149 .period_count = 512,
150 .format = PCM_FORMAT_S16_LE,
151 .start_threshold = 0,
152 .stop_threshold = INT_MAX,
153 .silence_threshold = 0,
154 .silence_size = 0,
155 .avail_min = ULL_PERIOD_SIZE, //1 ms
156};
157
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700158#define AFE_PROXY_CHANNEL_COUNT 2
159#define AFE_PROXY_SAMPLING_RATE 48000
160
161#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
162#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
163
164struct pcm_config pcm_config_afe_proxy_playback = {
165 .channels = AFE_PROXY_CHANNEL_COUNT,
166 .rate = AFE_PROXY_SAMPLING_RATE,
167 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
168 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
169 .format = PCM_FORMAT_S16_LE,
170 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
171 .stop_threshold = INT_MAX,
172 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
173};
174
175#define AFE_PROXY_RECORD_PERIOD_SIZE 768
176#define AFE_PROXY_RECORD_PERIOD_COUNT 4
177
178struct pcm_config pcm_config_afe_proxy_record = {
179 .channels = AFE_PROXY_CHANNEL_COUNT,
180 .rate = AFE_PROXY_SAMPLING_RATE,
181 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
182 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
183 .format = PCM_FORMAT_S16_LE,
184 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
185 .stop_threshold = INT_MAX,
186 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
187};
188
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700189const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700190 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
191 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
192 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700193 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700194 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700195 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700196
Eric Laurentb23d5282013-05-14 15:27:20 -0700197 [USECASE_AUDIO_RECORD] = "audio-record",
198 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700199
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800200 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
201 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700202
Eric Laurentb23d5282013-05-14 15:27:20 -0700203 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700204 [USECASE_VOICE2_CALL] = "voice2-call",
205 [USECASE_VOLTE_CALL] = "volte-call",
206 [USECASE_QCHAT_CALL] = "qchat-call",
207 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800208 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
209 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700210
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700211 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
212 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
213
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700214 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
215 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700216};
217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800218
219#define STRING_TO_ENUM(string) { #string, string }
220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800221struct string_to_enum {
222 const char *name;
223 uint32_t value;
224};
225
226static const struct string_to_enum out_channels_name_to_enum_table[] = {
227 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
228 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
229 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
230};
231
Haynes Mathew George5191a852013-09-11 14:19:36 -0700232static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700233static struct audio_device *adev = NULL;
234static pthread_mutex_t adev_init_lock;
235static unsigned int audio_device_ref_count;
236
Haynes Mathew George03c40102016-01-29 17:57:48 -0800237static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
238 int flags __unused)
239{
240 int dir = 0;
241 switch (uc_id) {
242 case USECASE_AUDIO_RECORD_LOW_LATENCY:
243 dir = 1;
244 case USECASE_AUDIO_PLAYBACK_ULL:
245 break;
246 default:
247 return false;
248 }
249
250 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
251 PCM_PLAYBACK : PCM_CAPTURE);
252 if (adev->adm_is_noirq_avail)
253 return adev->adm_is_noirq_avail(adev->adm_data,
254 adev->snd_card, dev_id, dir);
255 return false;
256}
257
258static void register_out_stream(struct stream_out *out)
259{
260 struct audio_device *adev = out->dev;
261 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
262 return;
263
264 if (!adev->adm_register_output_stream)
265 return;
266
267 adev->adm_register_output_stream(adev->adm_data,
268 out->handle,
269 out->flags);
270
271 if (!adev->adm_set_config)
272 return;
273
274 if (out->realtime) {
275 adev->adm_set_config(adev->adm_data,
276 out->handle,
277 out->pcm, &out->config);
278 }
279}
280
281static void register_in_stream(struct stream_in *in)
282{
283 struct audio_device *adev = in->dev;
284 if (!adev->adm_register_input_stream)
285 return;
286
287 adev->adm_register_input_stream(adev->adm_data,
288 in->capture_handle,
289 in->flags);
290
291 if (!adev->adm_set_config)
292 return;
293
294 if (in->realtime) {
295 adev->adm_set_config(adev->adm_data,
296 in->capture_handle,
297 in->pcm,
298 &in->config);
299 }
300}
301
302static void request_out_focus(struct stream_out *out, long ns)
303{
304 struct audio_device *adev = out->dev;
305
306 if (out->routing_change) {
307 out->routing_change = false;
308 if (adev->adm_on_routing_change)
309 adev->adm_on_routing_change(adev->adm_data, out->handle);
310 }
311
312 if (adev->adm_request_focus_v2) {
313 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
314 } else if (adev->adm_request_focus) {
315 adev->adm_request_focus(adev->adm_data, out->handle);
316 }
317}
318
319static void request_in_focus(struct stream_in *in, long ns)
320{
321 struct audio_device *adev = in->dev;
322
323 if (in->routing_change) {
324 in->routing_change = false;
325 if (adev->adm_on_routing_change)
326 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
327 }
328
329 if (adev->adm_request_focus_v2) {
330 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
331 } else if (adev->adm_request_focus) {
332 adev->adm_request_focus(adev->adm_data, in->capture_handle);
333 }
334}
335
336static void release_out_focus(struct stream_out *out, long ns __unused)
337{
338 struct audio_device *adev = out->dev;
339
340 if (adev->adm_abandon_focus)
341 adev->adm_abandon_focus(adev->adm_data, out->handle);
342}
343
344static void release_in_focus(struct stream_in *in, long ns __unused)
345{
346 struct audio_device *adev = in->dev;
347 if (adev->adm_abandon_focus)
348 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
349}
350
vivek mehta1a9b7c02015-06-25 11:49:38 -0700351__attribute__ ((visibility ("default")))
352bool audio_hw_send_gain_dep_calibration(int level) {
353 bool ret_val = false;
354 ALOGV("%s: enter ... ", __func__);
355
356 pthread_mutex_lock(&adev_init_lock);
357
358 if (adev != NULL && adev->platform != NULL) {
359 pthread_mutex_lock(&adev->lock);
360 ret_val = platform_send_gain_dep_cal(adev->platform, level);
361 pthread_mutex_unlock(&adev->lock);
362 } else {
363 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
364 }
365
366 pthread_mutex_unlock(&adev_init_lock);
367
368 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
369 return ret_val;
370}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700371
vivek mehtaa8d7c922016-05-25 14:40:44 -0700372__attribute__ ((visibility ("default")))
373int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
374 int table_size) {
375 int ret_val = 0;
376 ALOGV("%s: enter ... ", __func__);
377
378 pthread_mutex_lock(&adev_init_lock);
379 if (adev == NULL) {
380 ALOGW("%s: adev is NULL .... ", __func__);
381 goto done;
382 }
383
384 pthread_mutex_lock(&adev->lock);
385 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
386 pthread_mutex_unlock(&adev->lock);
387done:
388 pthread_mutex_unlock(&adev_init_lock);
389 ALOGV("%s: exit ... ", __func__);
390 return ret_val;
391}
392
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700393static bool is_supported_format(audio_format_t format)
394{
Eric Laurent8251ac82014-07-23 11:00:25 -0700395 switch (format) {
396 case AUDIO_FORMAT_MP3:
397 case AUDIO_FORMAT_AAC_LC:
398 case AUDIO_FORMAT_AAC_HE_V1:
399 case AUDIO_FORMAT_AAC_HE_V2:
400 return true;
401 default:
402 break;
403 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700404 return false;
405}
406
Haynes Mathew George03c40102016-01-29 17:57:48 -0800407static inline bool is_mmap_usecase(audio_usecase_t uc_id)
408{
409 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
410 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
411}
412
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700413static int get_snd_codec_id(audio_format_t format)
414{
415 int id = 0;
416
Eric Laurent8251ac82014-07-23 11:00:25 -0700417 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700418 case AUDIO_FORMAT_MP3:
419 id = SND_AUDIOCODEC_MP3;
420 break;
421 case AUDIO_FORMAT_AAC:
422 id = SND_AUDIOCODEC_AAC;
423 break;
424 default:
425 ALOGE("%s: Unsupported audio format", __func__);
426 }
427
428 return id;
429}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800430
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800431int enable_audio_route(struct audio_device *adev,
432 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700434 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800435 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800436
437 if (usecase == NULL)
438 return -EINVAL;
439
440 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
441
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800442 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700443 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800444 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700445 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800446
447 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500448 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Joe Onorato188b6222016-03-01 11:02:27 -0800449 ALOGV("%s: apply and update mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700450 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800452 ALOGV("%s: exit", __func__);
453 return 0;
454}
455
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800456int disable_audio_route(struct audio_device *adev,
457 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700459 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800460 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800461
462 if (usecase == NULL)
463 return -EINVAL;
464
465 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700466 if (usecase->type == PCM_CAPTURE)
467 snd_device = usecase->in_snd_device;
468 else
469 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800470 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500471 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Joe Onorato188b6222016-03-01 11:02:27 -0800472 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700473 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800474
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800475 ALOGV("%s: exit", __func__);
476 return 0;
477}
478
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800479int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700480 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800481{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700482 int i, num_devices = 0;
483 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800484 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800485 if (snd_device < SND_DEVICE_MIN ||
486 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800487 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800488 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800489 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700490
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700491 platform_send_audio_calibration(adev->platform, snd_device);
492
vivek mehtade4849c2016-03-03 17:23:38 -0800493 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700494 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700495 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800496 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700497 }
498
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700499 /* due to the possibility of calibration overwrite between listen
500 and audio, notify sound trigger hal before audio calibration is sent */
501 audio_extn_sound_trigger_update_device_status(snd_device,
502 ST_EVENT_SND_DEVICE_BUSY);
503
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700504 if (audio_extn_spkr_prot_is_enabled())
505 audio_extn_spkr_prot_calib_cancel(adev);
506
zhaoyang yin4211fad2015-06-04 21:13:25 +0800507 audio_extn_dsm_feedback_enable(adev, snd_device, true);
508
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700509 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
510 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
511 audio_extn_spkr_prot_is_enabled()) {
512 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800513 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700514 }
515 if (audio_extn_spkr_prot_start_processing(snd_device)) {
516 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800517 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700518 }
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700519 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
520 for (i = 0; i < num_devices; i++) {
521 enable_snd_device(adev, new_snd_devices[i]);
522 }
vivek mehtab6506412015-08-07 16:55:17 -0700523 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700524 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800525 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
526 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
527 ALOGE(" %s: Invalid sound device returned", __func__);
528 goto on_error;
529 }
Ed Tam70b5c142016-03-21 19:14:29 -0700530
vivek mehtade4849c2016-03-03 17:23:38 -0800531 ALOGV("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
532 audio_route_apply_and_update_path(adev->audio_route, device_name);
533 }
534on_success:
535 adev->snd_dev_ref_cnt[snd_device]++;
536 ret_val = 0;
537on_error:
538 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800539}
540
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800541int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700542 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800543{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700544 int i, num_devices = 0;
545 snd_device_t new_snd_devices[2];
546
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800547 if (snd_device < SND_DEVICE_MIN ||
548 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800549 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800550 return -EINVAL;
551 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700552 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
553 ALOGE("%s: device ref cnt is already 0", __func__);
554 return -EINVAL;
555 }
556 adev->snd_dev_ref_cnt[snd_device]--;
557 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800558 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700559 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
560 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
561 audio_extn_spkr_prot_is_enabled()) {
562 audio_extn_spkr_prot_stop_processing(snd_device);
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700563 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
564 for (i = 0; i < num_devices; i++) {
565 disable_snd_device(adev, new_snd_devices[i]);
566 }
vivek mehtab6506412015-08-07 16:55:17 -0700567 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700568 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800569 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
570 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
571 ALOGE(" %s: Invalid sound device returned", __func__);
572 return -EINVAL;
573 }
574
575 ALOGV("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
576 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700577 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700578 audio_extn_sound_trigger_update_device_status(snd_device,
579 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700580 }
vivek mehtab6506412015-08-07 16:55:17 -0700581
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800582 return 0;
583}
584
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700585static void check_and_route_playback_usecases(struct audio_device *adev,
586 struct audio_usecase *uc_info,
587 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700588{
589 struct listnode *node;
590 struct audio_usecase *usecase;
591 bool switch_device[AUDIO_USECASE_MAX];
592 int i, num_uc_to_switch = 0;
593
594 /*
595 * This function is to make sure that all the usecases that are active on
596 * the hardware codec backend are always routed to any one device that is
597 * handled by the hardware codec.
598 * For example, if low-latency and deep-buffer usecases are currently active
599 * on speaker and out_set_parameters(headset) is received on low-latency
600 * output, then we have to make sure deep-buffer is also switched to headset,
601 * because of the limitation that both the devices cannot be enabled
602 * at the same time as they share the same backend.
603 */
604 /* Disable all the usecases on the shared backend other than the
605 specified usecase */
606 for (i = 0; i < AUDIO_USECASE_MAX; i++)
607 switch_device[i] = false;
608
609 list_for_each(node, &adev->usecase_list) {
610 usecase = node_to_item(node, struct audio_usecase, list);
611 if (usecase->type != PCM_CAPTURE &&
612 usecase != uc_info &&
613 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700614 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
615 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
617 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700618 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700619 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700620 switch_device[usecase->id] = true;
621 num_uc_to_switch++;
622 }
623 }
624
625 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700626 list_for_each(node, &adev->usecase_list) {
627 usecase = node_to_item(node, struct audio_usecase, list);
628 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700629 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900630 }
631 }
632
633 list_for_each(node, &adev->usecase_list) {
634 usecase = node_to_item(node, struct audio_usecase, list);
635 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700636 enable_snd_device(adev, snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637 }
638 }
639
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640 /* Re-route all the usecases on the shared backend other than the
641 specified usecase to new snd devices */
642 list_for_each(node, &adev->usecase_list) {
643 usecase = node_to_item(node, struct audio_usecase, list);
644 /* Update the out_snd_device only before enabling the audio route */
645 if (switch_device[usecase->id] ) {
646 usecase->out_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700647 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700648 }
649 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700650 }
651}
652
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700653static void check_and_route_capture_usecases(struct audio_device *adev,
654 struct audio_usecase *uc_info,
655 snd_device_t snd_device)
656{
657 struct listnode *node;
658 struct audio_usecase *usecase;
659 bool switch_device[AUDIO_USECASE_MAX];
660 int i, num_uc_to_switch = 0;
661
vivek mehta4ed66e62016-04-15 23:33:34 -0700662 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
663
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700664 /*
665 * This function is to make sure that all the active capture usecases
666 * are always routed to the same input sound device.
667 * For example, if audio-record and voice-call usecases are currently
668 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
669 * is received for voice call then we have to make sure that audio-record
670 * usecase is also switched to earpiece i.e. voice-dmic-ef,
671 * because of the limitation that two devices cannot be enabled
672 * at the same time if they share the same backend.
673 */
674 for (i = 0; i < AUDIO_USECASE_MAX; i++)
675 switch_device[i] = false;
676
677 list_for_each(node, &adev->usecase_list) {
678 usecase = node_to_item(node, struct audio_usecase, list);
679 if (usecase->type != PCM_PLAYBACK &&
680 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700681 usecase->in_snd_device != snd_device &&
682 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700683 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
684 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700685 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700686 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700687 switch_device[usecase->id] = true;
688 num_uc_to_switch++;
689 }
690 }
691
692 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700693 list_for_each(node, &adev->usecase_list) {
694 usecase = node_to_item(node, struct audio_usecase, list);
695 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700696 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700697 }
698 }
699
700 list_for_each(node, &adev->usecase_list) {
701 usecase = node_to_item(node, struct audio_usecase, list);
702 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700703 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700704 }
705 }
706
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700707 /* Re-route all the usecases on the shared backend other than the
708 specified usecase to new snd devices */
709 list_for_each(node, &adev->usecase_list) {
710 usecase = node_to_item(node, struct audio_usecase, list);
711 /* Update the in_snd_device only before enabling the audio route */
712 if (switch_device[usecase->id] ) {
713 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700714 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700715 }
716 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700717 }
718}
719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800720/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700721static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700723 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700724 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800725
726 switch (channels) {
727 /*
728 * Do not handle stereo output in Multi-channel cases
729 * Stereo case is handled in normal playback path
730 */
731 case 6:
732 ALOGV("%s: HDMI supports 5.1", __func__);
733 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
734 break;
735 case 8:
736 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
737 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
738 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
739 break;
740 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700741 ALOGE("HDMI does not support multi channel playback");
742 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800743 break;
744 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700745 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800746}
747
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700748static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
749{
750 struct audio_usecase *usecase;
751 struct listnode *node;
752
753 list_for_each(node, &adev->usecase_list) {
754 usecase = node_to_item(node, struct audio_usecase, list);
755 if (usecase->type == VOICE_CALL) {
756 ALOGV("%s: usecase id %d", __func__, usecase->id);
757 return usecase->id;
758 }
759 }
760 return USECASE_INVALID;
761}
762
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800763struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
764 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700765{
766 struct audio_usecase *usecase;
767 struct listnode *node;
768
769 list_for_each(node, &adev->usecase_list) {
770 usecase = node_to_item(node, struct audio_usecase, list);
771 if (usecase->id == uc_id)
772 return usecase;
773 }
774 return NULL;
775}
776
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800777int select_devices(struct audio_device *adev,
778 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800779{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800780 snd_device_t out_snd_device = SND_DEVICE_NONE;
781 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700782 struct audio_usecase *usecase = NULL;
783 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800784 struct audio_usecase *hfp_usecase = NULL;
785 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800786 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700787 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800788
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700789 usecase = get_usecase_from_list(adev, uc_id);
790 if (usecase == NULL) {
791 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
792 return -EINVAL;
793 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800794
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800795 if ((usecase->type == VOICE_CALL) ||
796 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700797 out_snd_device = platform_get_output_snd_device(adev->platform,
798 usecase->stream.out->devices);
799 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700800 usecase->devices = usecase->stream.out->devices;
801 } else {
802 /*
803 * If the voice call is active, use the sound devices of voice call usecase
804 * so that it would not result any device switch. All the usecases will
805 * be switched to new device when select_devices() is called for voice call
806 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700807 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700808 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700809 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700810 vc_usecase = get_usecase_from_list(adev,
811 get_voice_usecase_id_from_list(adev));
812 if ((vc_usecase != NULL) &&
813 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
814 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700815 in_snd_device = vc_usecase->in_snd_device;
816 out_snd_device = vc_usecase->out_snd_device;
817 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800818 } else if (audio_extn_hfp_is_active(adev)) {
819 hfp_ucid = audio_extn_hfp_get_usecase();
820 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
821 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
822 in_snd_device = hfp_usecase->in_snd_device;
823 out_snd_device = hfp_usecase->out_snd_device;
824 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700825 }
826 if (usecase->type == PCM_PLAYBACK) {
827 usecase->devices = usecase->stream.out->devices;
828 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700829 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700830 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700831 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700832 if (usecase->stream.out == adev->primary_output &&
833 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -0700834 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
835 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800836 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700837 select_devices(adev, adev->active_input->usecase);
838 }
839 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700840 } else if (usecase->type == PCM_CAPTURE) {
841 usecase->devices = usecase->stream.in->device;
842 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700843 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700844 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -0700845 if (adev->active_input &&
846 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
847 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800848 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -0700849 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
850 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
851 } else if (adev->primary_output) {
852 out_device = adev->primary_output->devices;
853 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700854 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700855 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700856 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857 }
858 }
859
860 if (out_snd_device == usecase->out_snd_device &&
861 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800862 return 0;
863 }
864
Eric Laurent2bafff12016-03-17 12:17:23 -0700865 if (out_snd_device != SND_DEVICE_NONE &&
866 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
867 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
868 __func__,
869 use_case_table[uc_id],
870 adev->last_logged_snd_device[uc_id][0],
871 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
872 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
873 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
874 -1,
875 out_snd_device,
876 platform_get_snd_device_name(out_snd_device),
877 platform_get_snd_device_acdb_id(out_snd_device));
878 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
879 }
880 if (in_snd_device != SND_DEVICE_NONE &&
881 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
882 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
883 __func__,
884 use_case_table[uc_id],
885 adev->last_logged_snd_device[uc_id][1],
886 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
887 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
888 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
889 -1,
890 in_snd_device,
891 platform_get_snd_device_name(in_snd_device),
892 platform_get_snd_device_acdb_id(in_snd_device));
893 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
894 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800896 /*
897 * Limitation: While in call, to do a device switch we need to disable
898 * and enable both RX and TX devices though one of them is same as current
899 * device.
900 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700901 if ((usecase->type == VOICE_CALL) &&
902 (usecase->in_snd_device != SND_DEVICE_NONE) &&
903 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700904 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -0700905 /* Disable sidetone only if voice call already exists */
906 if (voice_is_call_state_active(adev))
907 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800908 }
909
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700910 /* Disable current sound devices */
911 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700912 disable_audio_route(adev, usecase);
913 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800914 }
915
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700916 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700917 disable_audio_route(adev, usecase);
918 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800919 }
920
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700921 /* Applicable only on the targets that has external modem.
922 * New device information should be sent to modem before enabling
923 * the devices to reduce in-call device switch time.
924 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700925 if ((usecase->type == VOICE_CALL) &&
926 (usecase->in_snd_device != SND_DEVICE_NONE) &&
927 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700928 status = platform_switch_voice_call_enable_device_config(adev->platform,
929 out_snd_device,
930 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700931 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700932
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 /* Enable new sound devices */
934 if (out_snd_device != SND_DEVICE_NONE) {
935 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700936 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700937 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800938 }
939
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700940 if (in_snd_device != SND_DEVICE_NONE) {
941 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700942 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700943 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700944
Eric Laurentb23d5282013-05-14 15:27:20 -0700945 if (usecase->type == VOICE_CALL)
946 status = platform_switch_voice_call_device_post(adev->platform,
947 out_snd_device,
948 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800949
sangwoo170731f2013-06-08 15:36:36 +0900950 usecase->in_snd_device = in_snd_device;
951 usecase->out_snd_device = out_snd_device;
952
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700953 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900954
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700955 /* Applicable only on the targets that has external modem.
956 * Enable device command should be sent to modem only after
957 * enabling voice call mixer controls
958 */
vivek mehta765eb642015-08-07 19:46:06 -0700959 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700960 status = platform_switch_voice_call_usecase_route_post(adev->platform,
961 out_snd_device,
962 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -0700963 /* Enable sidetone only if voice call already exists */
964 if (voice_is_call_state_active(adev))
965 voice_set_sidetone(adev, out_snd_device, true);
966 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968 return status;
969}
970
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971static int stop_input_stream(struct stream_in *in)
972{
973 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800974 struct audio_usecase *uc_info;
975 struct audio_device *adev = in->dev;
976
Eric Laurentc8400632013-02-14 19:04:54 -0800977 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800978
Eric Laurent994a6932013-07-17 11:51:42 -0700979 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700980 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981 uc_info = get_usecase_from_list(adev, in->usecase);
982 if (uc_info == NULL) {
983 ALOGE("%s: Could not find the usecase (%d) in the list",
984 __func__, in->usecase);
985 return -EINVAL;
986 }
987
Eric Laurent150dbfe2013-02-27 14:31:02 -0800988 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700989 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990
991 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700992 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800993
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800994 list_remove(&uc_info->list);
995 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800996
Eric Laurent994a6932013-07-17 11:51:42 -0700997 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800998 return ret;
999}
1000
1001int start_input_stream(struct stream_in *in)
1002{
1003 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001004 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001005 struct audio_usecase *uc_info;
1006 struct audio_device *adev = in->dev;
1007
Eric Laurent994a6932013-07-17 11:51:42 -07001008 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Eric Laurentb23d5282013-05-14 15:27:20 -07001009 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001010 if (in->pcm_device_id < 0) {
1011 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1012 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001013 ret = -EINVAL;
1014 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001015 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001016
1017 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1019 uc_info->id = in->usecase;
1020 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001021 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001022 uc_info->devices = in->device;
1023 uc_info->in_snd_device = SND_DEVICE_NONE;
1024 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001026 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001027
1028 audio_extn_perf_lock_acquire();
1029
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001030 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031
Eric Laurentc8400632013-02-14 19:04:54 -08001032 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001033 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001034
Andy Hung6ebe5962016-01-15 17:46:57 -08001035 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001036 unsigned int pcm_open_retry_count = 0;
1037
1038 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1039 flags |= PCM_MMAP | PCM_NOIRQ;
1040 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001041 } else if (in->realtime) {
1042 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001043 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001044
1045 while (1) {
1046 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1047 flags, &in->config);
1048 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1049 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1050 if (in->pcm != NULL) {
1051 pcm_close(in->pcm);
1052 in->pcm = NULL;
1053 }
1054 if (pcm_open_retry_count-- == 0) {
1055 ret = -EIO;
1056 goto error_open;
1057 }
1058 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1059 continue;
1060 }
1061 break;
1062 }
1063
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001064 ALOGV("%s: pcm_prepare", __func__);
1065 ret = pcm_prepare(in->pcm);
1066 if (ret < 0) {
1067 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1068 pcm_close(in->pcm);
1069 in->pcm = NULL;
1070 goto error_open;
1071 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001072 register_in_stream(in);
1073 if (in->realtime) {
1074 ret = pcm_start(in->pcm);
1075 }
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001076 audio_extn_perf_lock_release();
1077
Eric Laurent994a6932013-07-17 11:51:42 -07001078 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001079
Eric Laurentc8400632013-02-14 19:04:54 -08001080 return ret;
1081
1082error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001084 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001085
1086error_config:
1087 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001088 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001089
1090 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091}
1092
Eric Laurenta1478072015-09-21 17:21:52 -07001093void lock_input_stream(struct stream_in *in)
1094{
1095 pthread_mutex_lock(&in->pre_lock);
1096 pthread_mutex_lock(&in->lock);
1097 pthread_mutex_unlock(&in->pre_lock);
1098}
1099
1100void lock_output_stream(struct stream_out *out)
1101{
1102 pthread_mutex_lock(&out->pre_lock);
1103 pthread_mutex_lock(&out->lock);
1104 pthread_mutex_unlock(&out->pre_lock);
1105}
1106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001107/* must be called with out->lock locked */
1108static int send_offload_cmd_l(struct stream_out* out, int command)
1109{
1110 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1111
1112 ALOGVV("%s %d", __func__, command);
1113
1114 cmd->cmd = command;
1115 list_add_tail(&out->offload_cmd_list, &cmd->node);
1116 pthread_cond_signal(&out->offload_cond);
1117 return 0;
1118}
1119
1120/* must be called iwth out->lock locked */
1121static void stop_compressed_output_l(struct stream_out *out)
1122{
1123 out->offload_state = OFFLOAD_STATE_IDLE;
1124 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001125 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001126 if (out->compr != NULL) {
1127 compress_stop(out->compr);
1128 while (out->offload_thread_blocked) {
1129 pthread_cond_wait(&out->cond, &out->lock);
1130 }
1131 }
1132}
1133
1134static void *offload_thread_loop(void *context)
1135{
1136 struct stream_out *out = (struct stream_out *) context;
1137 struct listnode *item;
1138
1139 out->offload_state = OFFLOAD_STATE_IDLE;
1140 out->playback_started = 0;
1141
1142 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1143 set_sched_policy(0, SP_FOREGROUND);
1144 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1145
1146 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001147 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001148 for (;;) {
1149 struct offload_cmd *cmd = NULL;
1150 stream_callback_event_t event;
1151 bool send_callback = false;
1152
1153 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1154 __func__, list_empty(&out->offload_cmd_list),
1155 out->offload_state);
1156 if (list_empty(&out->offload_cmd_list)) {
1157 ALOGV("%s SLEEPING", __func__);
1158 pthread_cond_wait(&out->offload_cond, &out->lock);
1159 ALOGV("%s RUNNING", __func__);
1160 continue;
1161 }
1162
1163 item = list_head(&out->offload_cmd_list);
1164 cmd = node_to_item(item, struct offload_cmd, node);
1165 list_remove(item);
1166
1167 ALOGVV("%s STATE %d CMD %d out->compr %p",
1168 __func__, out->offload_state, cmd->cmd, out->compr);
1169
1170 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1171 free(cmd);
1172 break;
1173 }
1174
1175 if (out->compr == NULL) {
1176 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001177 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001178 pthread_cond_signal(&out->cond);
1179 continue;
1180 }
1181 out->offload_thread_blocked = true;
1182 pthread_mutex_unlock(&out->lock);
1183 send_callback = false;
1184 switch(cmd->cmd) {
1185 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1186 compress_wait(out->compr, -1);
1187 send_callback = true;
1188 event = STREAM_CBK_EVENT_WRITE_READY;
1189 break;
1190 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001191 compress_next_track(out->compr);
1192 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001193 send_callback = true;
1194 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001195 /* Resend the metadata for next iteration */
1196 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001197 break;
1198 case OFFLOAD_CMD_DRAIN:
1199 compress_drain(out->compr);
1200 send_callback = true;
1201 event = STREAM_CBK_EVENT_DRAIN_READY;
1202 break;
1203 default:
1204 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1205 break;
1206 }
Eric Laurenta1478072015-09-21 17:21:52 -07001207 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001208 out->offload_thread_blocked = false;
1209 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001210 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001211 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001212 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001213 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001214 free(cmd);
1215 }
1216
1217 pthread_cond_signal(&out->cond);
1218 while (!list_empty(&out->offload_cmd_list)) {
1219 item = list_head(&out->offload_cmd_list);
1220 list_remove(item);
1221 free(node_to_item(item, struct offload_cmd, node));
1222 }
1223 pthread_mutex_unlock(&out->lock);
1224
1225 return NULL;
1226}
1227
1228static int create_offload_callback_thread(struct stream_out *out)
1229{
1230 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1231 list_init(&out->offload_cmd_list);
1232 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1233 offload_thread_loop, out);
1234 return 0;
1235}
1236
1237static int destroy_offload_callback_thread(struct stream_out *out)
1238{
Eric Laurenta1478072015-09-21 17:21:52 -07001239 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001240 stop_compressed_output_l(out);
1241 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1242
1243 pthread_mutex_unlock(&out->lock);
1244 pthread_join(out->offload_thread, (void **) NULL);
1245 pthread_cond_destroy(&out->offload_cond);
1246
1247 return 0;
1248}
1249
Eric Laurent07eeafd2013-10-06 12:52:49 -07001250static bool allow_hdmi_channel_config(struct audio_device *adev)
1251{
1252 struct listnode *node;
1253 struct audio_usecase *usecase;
1254 bool ret = true;
1255
1256 list_for_each(node, &adev->usecase_list) {
1257 usecase = node_to_item(node, struct audio_usecase, list);
1258 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1259 /*
1260 * If voice call is already existing, do not proceed further to avoid
1261 * disabling/enabling both RX and TX devices, CSD calls, etc.
1262 * Once the voice call done, the HDMI channels can be configured to
1263 * max channels of remaining use cases.
1264 */
1265 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001266 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001267 __func__);
1268 ret = false;
1269 break;
1270 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001271 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001272 "no change in HDMI channels", __func__);
1273 ret = false;
1274 break;
1275 }
1276 }
1277 }
1278 return ret;
1279}
1280
1281static int check_and_set_hdmi_channels(struct audio_device *adev,
1282 unsigned int channels)
1283{
1284 struct listnode *node;
1285 struct audio_usecase *usecase;
1286
1287 /* Check if change in HDMI channel config is allowed */
1288 if (!allow_hdmi_channel_config(adev))
1289 return 0;
1290
1291 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001292 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001293 return 0;
1294 }
1295
1296 platform_set_hdmi_channels(adev->platform, channels);
1297 adev->cur_hdmi_channels = channels;
1298
1299 /*
1300 * Deroute all the playback streams routed to HDMI so that
1301 * the back end is deactivated. Note that backend will not
1302 * be deactivated if any one stream is connected to it.
1303 */
1304 list_for_each(node, &adev->usecase_list) {
1305 usecase = node_to_item(node, struct audio_usecase, list);
1306 if (usecase->type == PCM_PLAYBACK &&
1307 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001308 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001309 }
1310 }
1311
1312 /*
1313 * Enable all the streams disabled above. Now the HDMI backend
1314 * will be activated with new channel configuration
1315 */
1316 list_for_each(node, &adev->usecase_list) {
1317 usecase = node_to_item(node, struct audio_usecase, list);
1318 if (usecase->type == PCM_PLAYBACK &&
1319 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001320 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001321 }
1322 }
1323
1324 return 0;
1325}
1326
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001327static int stop_output_stream(struct stream_out *out)
1328{
1329 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001330 struct audio_usecase *uc_info;
1331 struct audio_device *adev = out->dev;
1332
Eric Laurent994a6932013-07-17 11:51:42 -07001333 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001334 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001335 uc_info = get_usecase_from_list(adev, out->usecase);
1336 if (uc_info == NULL) {
1337 ALOGE("%s: Could not find the usecase (%d) in the list",
1338 __func__, out->usecase);
1339 return -EINVAL;
1340 }
1341
Haynes Mathew George41f86652014-06-17 14:22:15 -07001342 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1343 if (adev->visualizer_stop_output != NULL)
1344 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1345 if (adev->offload_effects_stop_output != NULL)
1346 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1347 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001348
Eric Laurent150dbfe2013-02-27 14:31:02 -08001349 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001350 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001351
1352 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001353 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001354
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001355 list_remove(&uc_info->list);
1356 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001357
Eric Laurent0499d4f2014-08-25 22:39:29 -05001358 audio_extn_extspk_update(adev->extspk);
1359
Eric Laurent07eeafd2013-10-06 12:52:49 -07001360 /* Must be called after removing the usecase from list */
1361 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1362 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1363
Eric Laurent994a6932013-07-17 11:51:42 -07001364 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001365 return ret;
1366}
1367
1368int start_output_stream(struct stream_out *out)
1369{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001370 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001371 struct audio_usecase *uc_info;
1372 struct audio_device *adev = out->dev;
1373
Eric Laurent994a6932013-07-17 11:51:42 -07001374 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001375 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001376 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001377 if (out->pcm_device_id < 0) {
1378 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1379 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001380 ret = -EINVAL;
1381 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001382 }
1383
1384 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1385 uc_info->id = out->usecase;
1386 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001387 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001388 uc_info->devices = out->devices;
1389 uc_info->in_snd_device = SND_DEVICE_NONE;
1390 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001391
Eric Laurent07eeafd2013-10-06 12:52:49 -07001392 /* This must be called before adding this usecase to the list */
1393 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1394 check_and_set_hdmi_channels(adev, out->config.channels);
1395
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001396 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001397
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001398 audio_extn_perf_lock_acquire();
1399
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001400 select_devices(adev, out->usecase);
1401
Eric Laurent0499d4f2014-08-25 22:39:29 -05001402 audio_extn_extspk_update(adev->extspk);
1403
Andy Hung31aca912014-03-20 17:14:59 -07001404 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001405 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001406 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001407 unsigned int flags = PCM_OUT;
1408 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001409
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001410 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1411 flags |= PCM_MMAP | PCM_NOIRQ;
1412 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001413 } else if (out->realtime) {
1414 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001415 } else
1416 flags |= PCM_MONOTONIC;
1417
1418 while (1) {
1419 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1420 flags, &out->config);
1421 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1422 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1423 if (out->pcm != NULL) {
1424 pcm_close(out->pcm);
1425 out->pcm = NULL;
1426 }
1427 if (pcm_open_retry_count-- == 0) {
1428 ret = -EIO;
1429 goto error_open;
1430 }
1431 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1432 continue;
1433 }
1434 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001435 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001436 ALOGV("%s: pcm_prepare", __func__);
1437 if (pcm_is_ready(out->pcm)) {
1438 ret = pcm_prepare(out->pcm);
1439 if (ret < 0) {
1440 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1441 pcm_close(out->pcm);
1442 out->pcm = NULL;
1443 goto error_open;
1444 }
1445 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001446 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001448 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001449 COMPRESS_IN, &out->compr_config);
1450 if (out->compr && !is_compress_ready(out->compr)) {
1451 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1452 compress_close(out->compr);
1453 out->compr = NULL;
1454 ret = -EIO;
1455 goto error_open;
1456 }
1457 if (out->offload_callback)
1458 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001459
1460 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001461 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1462 if (adev->offload_effects_start_output != NULL)
1463 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001464 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001465 ret = 0;
1466 register_out_stream(out);
1467 if (out->realtime) {
1468 ret = pcm_start(out->pcm);
1469 }
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001470 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001471 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001472 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001473error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001474 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001475 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001476error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001477 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478}
1479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480static int check_input_parameters(uint32_t sample_rate,
1481 audio_format_t format,
1482 int channel_count)
1483{
vivek mehta4ed66e62016-04-15 23:33:34 -07001484 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001485 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1486 return -EINVAL;
1487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488
vivek mehtadae44712015-07-27 14:13:18 -07001489 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001490 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001491 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1492 return -EINVAL;
1493 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494
1495 switch (sample_rate) {
1496 case 8000:
1497 case 11025:
1498 case 12000:
1499 case 16000:
1500 case 22050:
1501 case 24000:
1502 case 32000:
1503 case 44100:
1504 case 48000:
1505 break;
1506 default:
vivek mehtadae44712015-07-27 14:13:18 -07001507 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508 return -EINVAL;
1509 }
1510
1511 return 0;
1512}
1513
1514static size_t get_input_buffer_size(uint32_t sample_rate,
1515 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001516 int channel_count,
1517 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518{
1519 size_t size = 0;
1520
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001521 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1522 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001524 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001525 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001526 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001527
1528 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529
Glenn Kasten4f993392014-05-14 07:30:48 -07001530 /* make sure the size is multiple of 32 bytes
1531 * At 48 kHz mono 16-bit PCM:
1532 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1533 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1534 */
1535 size += 0x1f;
1536 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001537
1538 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539}
1540
1541static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1542{
1543 struct stream_out *out = (struct stream_out *)stream;
1544
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001545 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001546}
1547
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001548static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001549{
1550 return -ENOSYS;
1551}
1552
1553static size_t out_get_buffer_size(const struct audio_stream *stream)
1554{
1555 struct stream_out *out = (struct stream_out *)stream;
1556
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001557 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1558 return out->compr_config.fragment_size;
1559 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001560 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001561 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001562}
1563
1564static uint32_t out_get_channels(const struct audio_stream *stream)
1565{
1566 struct stream_out *out = (struct stream_out *)stream;
1567
1568 return out->channel_mask;
1569}
1570
1571static audio_format_t out_get_format(const struct audio_stream *stream)
1572{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001573 struct stream_out *out = (struct stream_out *)stream;
1574
1575 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001576}
1577
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001578static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579{
1580 return -ENOSYS;
1581}
1582
1583static int out_standby(struct audio_stream *stream)
1584{
1585 struct stream_out *out = (struct stream_out *)stream;
1586 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001587
Eric Laurent994a6932013-07-17 11:51:42 -07001588 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001589 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590
Eric Laurenta1478072015-09-21 17:21:52 -07001591 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001593 if (adev->adm_deregister_stream)
1594 adev->adm_deregister_stream(adev->adm_data, out->handle);
1595
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001596 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001598 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1599 if (out->pcm) {
1600 pcm_close(out->pcm);
1601 out->pcm = NULL;
1602 }
1603 } else {
1604 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001605 out->gapless_mdata.encoder_delay = 0;
1606 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001607 if (out->compr != NULL) {
1608 compress_close(out->compr);
1609 out->compr = NULL;
1610 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001611 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001612 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001613 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001614 }
1615 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001616 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001617 return 0;
1618}
1619
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001620static int out_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001621{
1622 return 0;
1623}
1624
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001625static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1626{
1627 int ret = 0;
1628 char value[32];
1629 struct compr_gapless_mdata tmp_mdata;
1630
1631 if (!out || !parms) {
1632 return -EINVAL;
1633 }
1634
1635 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1636 if (ret >= 0) {
1637 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1638 } else {
1639 return -EINVAL;
1640 }
1641
1642 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1643 if (ret >= 0) {
1644 tmp_mdata.encoder_padding = atoi(value);
1645 } else {
1646 return -EINVAL;
1647 }
1648
1649 out->gapless_mdata = tmp_mdata;
1650 out->send_new_metadata = 1;
1651 ALOGV("%s new encoder delay %u and padding %u", __func__,
1652 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1653
1654 return 0;
1655}
1656
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001657static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1658{
1659 return out == adev->primary_output || out == adev->voice_tx_output;
1660}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1663{
1664 struct stream_out *out = (struct stream_out *)stream;
1665 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001666 struct audio_usecase *usecase;
1667 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668 struct str_parms *parms;
1669 char value[32];
1670 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001671 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001672 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673
Joe Onorato188b6222016-03-01 11:02:27 -08001674 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001675 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001676 parms = str_parms_create_str(kvpairs);
1677 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1678 if (ret >= 0) {
1679 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001680 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001681 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001683 /*
1684 * When HDMI cable is unplugged the music playback is paused and
1685 * the policy manager sends routing=0. But the audioflinger
1686 * continues to write data until standby time (3sec).
1687 * As the HDMI core is turned off, the write gets blocked.
1688 * Avoid this by routing audio to speaker until standby.
1689 */
1690 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1691 val == AUDIO_DEVICE_NONE) {
1692 val = AUDIO_DEVICE_OUT_SPEAKER;
1693 }
1694
1695 /*
1696 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001697 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001698 * the select_devices(). But how do we undo this?
1699 *
1700 * For example, music playback is active on headset (deep-buffer usecase)
1701 * and if we go to ringtones and select a ringtone, low-latency usecase
1702 * will be started on headset+speaker. As we can't enable headset+speaker
1703 * and headset devices at the same time, select_devices() switches the music
1704 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1705 * So when the ringtone playback is completed, how do we undo the same?
1706 *
1707 * We are relying on the out_set_parameters() call on deep-buffer output,
1708 * once the ringtone playback is ended.
1709 * NOTE: We should not check if the current devices are same as new devices.
1710 * Because select_devices() must be called to switch back the music
1711 * playback to headset.
1712 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08001713 audio_devices_t new_dev = val;
1714 if (new_dev != AUDIO_DEVICE_NONE) {
1715 bool same_dev = out->devices == new_dev;
1716 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001717
Haynes Mathew George03c40102016-01-29 17:57:48 -08001718 if (!out->standby) {
1719 if (!same_dev) {
1720 ALOGV("update routing change");
1721 out->routing_change = true;
1722 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001723 select_devices(adev, out->usecase);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001724 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001725
Eric Laurenta7657192014-10-09 21:09:33 -07001726 if (output_drives_call(adev, out)) {
1727 if (!voice_is_in_call(adev)) {
1728 if (adev->mode == AUDIO_MODE_IN_CALL) {
1729 adev->current_call_output = out;
1730 ret = voice_start_call(adev);
1731 }
1732 } else {
1733 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001734 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07001735 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001736 }
1737 }
1738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001740 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05001741
1742 /*handles device and call state changes*/
1743 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001744 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001745
1746 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1747 parse_compress_metadata(out, parms);
1748 }
1749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001750 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07001751 ALOGV("%s: exit: code(%d)", __func__, status);
1752 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753}
1754
1755static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1756{
1757 struct stream_out *out = (struct stream_out *)stream;
1758 struct str_parms *query = str_parms_create_str(keys);
1759 char *str;
1760 char value[256];
1761 struct str_parms *reply = str_parms_create();
1762 size_t i, j;
1763 int ret;
1764 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07001765 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001766 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1767 if (ret >= 0) {
1768 value[0] = '\0';
1769 i = 0;
1770 while (out->supported_channel_masks[i] != 0) {
1771 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1772 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1773 if (!first) {
1774 strcat(value, "|");
1775 }
1776 strcat(value, out_channels_name_to_enum_table[j].name);
1777 first = false;
1778 break;
1779 }
1780 }
1781 i++;
1782 }
1783 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1784 str = str_parms_to_str(reply);
1785 } else {
1786 str = strdup(keys);
1787 }
1788 str_parms_destroy(query);
1789 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001790 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 return str;
1792}
1793
1794static uint32_t out_get_latency(const struct audio_stream_out *stream)
1795{
Haynes Mathew George03c40102016-01-29 17:57:48 -08001796 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001797 struct stream_out *out = (struct stream_out *)stream;
1798
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001799 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
1800 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001801 else if (out->realtime) {
1802 // since the buffer won't be filled up faster than realtime,
1803 // return a smaller number
1804 period_ms = (out->af_period_multiplier * out->config.period_size *
1805 1000) / (out->config.rate);
1806 hw_delay = platform_render_latency(out->usecase)/1000;
1807 return period_ms + hw_delay;
1808 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001809
1810 return (out->config.period_count * out->config.period_size * 1000) /
1811 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812}
1813
1814static int out_set_volume(struct audio_stream_out *stream, float left,
1815 float right)
1816{
Eric Laurenta9024de2013-04-04 09:19:12 -07001817 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001818 int volume[2];
1819
Eric Laurenta9024de2013-04-04 09:19:12 -07001820 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1821 /* only take left channel into account: the API is for stereo anyway */
1822 out->muted = (left == 0.0f);
1823 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1825 const char *mixer_ctl_name = "Compress Playback Volume";
1826 struct audio_device *adev = out->dev;
1827 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001828 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1829 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07001830 /* try with the control based on device id */
1831 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
1832 PCM_PLAYBACK);
1833 char ctl_name[128] = {0};
1834 snprintf(ctl_name, sizeof(ctl_name),
1835 "Compress Playback %d Volume", pcm_device_id);
1836 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
1837 if (!ctl) {
1838 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
1839 return -EINVAL;
1840 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001841 }
1842 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
1843 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
1844 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
1845 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07001846 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001848 return -ENOSYS;
1849}
1850
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001851#ifdef NO_AUDIO_OUT
1852static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
1853 const void *buffer, size_t bytes)
1854{
1855 struct stream_out *out = (struct stream_out *)stream;
1856
1857 /* No Output device supported other than BT for playback.
1858 * Sleep for the amount of buffer duration
1859 */
Eric Laurenta1478072015-09-21 17:21:52 -07001860 lock_output_stream(out);
Uday Kishore Pasupuletib14d76b2015-11-13 20:06:37 -08001861 usleep(bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001862 out_get_sample_rate(&out->stream.common));
1863 pthread_mutex_unlock(&out->lock);
1864 return bytes;
1865}
1866#endif
1867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1869 size_t bytes)
1870{
1871 struct stream_out *out = (struct stream_out *)stream;
1872 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07001873 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874
Eric Laurenta1478072015-09-21 17:21:52 -07001875 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001876 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001877 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001878 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001880 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001881 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001883 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884 goto exit;
1885 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001887
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001888 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001889 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
1890 if (out->send_new_metadata) {
1891 ALOGVV("send new gapless metadata");
1892 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
1893 out->send_new_metadata = 0;
1894 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08001895 unsigned int avail;
1896 struct timespec tstamp;
1897 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
1898 /* Do not limit write size if the available frames count is unknown */
1899 if (ret != 0) {
1900 avail = bytes;
1901 }
1902 if (avail == 0) {
1903 ret = 0;
1904 } else {
1905 if (avail > bytes) {
1906 avail = bytes;
1907 }
1908 ret = compress_write(out->compr, buffer, avail);
1909 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
1910 __func__, avail, ret);
1911 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001912
Eric Laurent6e895242013-09-05 16:10:57 -07001913 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001914 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
1915 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08001916 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001917 compress_start(out->compr);
1918 out->playback_started = 1;
1919 out->offload_state = OFFLOAD_STATE_PLAYING;
1920 }
1921 pthread_mutex_unlock(&out->lock);
1922 return ret;
1923 } else {
1924 if (out->pcm) {
1925 if (out->muted)
1926 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001927
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001928 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001929
Haynes Mathew George03c40102016-01-29 17:57:48 -08001930 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
1931 out->config.rate;
1932 request_out_focus(out, ns);
1933
1934 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
1935 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001936 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001937 else
1938 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001939
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001940 if (ret == 0)
1941 out->written += bytes / (out->config.channels * sizeof(short));
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001942
Haynes Mathew George03c40102016-01-29 17:57:48 -08001943 release_out_focus(out, ns);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001944 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001945 }
1946
1947exit:
1948 pthread_mutex_unlock(&out->lock);
1949
1950 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001951 if (out->pcm)
vivek mehta1a9b7c02015-06-25 11:49:38 -07001952 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001953 out_standby(&out->stream.common);
Eric Laurentfdf296a2014-07-03 16:41:51 -07001954 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955 out_get_sample_rate(&out->stream.common));
1956 }
1957 return bytes;
1958}
1959
1960static int out_get_render_position(const struct audio_stream_out *stream,
1961 uint32_t *dsp_frames)
1962{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001963 struct stream_out *out = (struct stream_out *)stream;
1964 *dsp_frames = 0;
1965 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07001966 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001967 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08001968 unsigned long frames = 0;
1969 // TODO: check return value
1970 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
1971 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001972 ALOGVV("%s rendered frames %d sample_rate %d",
1973 __func__, *dsp_frames, out->sample_rate);
1974 }
1975 pthread_mutex_unlock(&out->lock);
1976 return 0;
1977 } else
1978 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979}
1980
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001981static int out_add_audio_effect(const struct audio_stream *stream __unused,
1982 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983{
1984 return 0;
1985}
1986
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001987static int out_remove_audio_effect(const struct audio_stream *stream __unused,
1988 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001989{
1990 return 0;
1991}
1992
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001993static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
1994 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001995{
1996 return -EINVAL;
1997}
1998
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001999static int out_get_presentation_position(const struct audio_stream_out *stream,
2000 uint64_t *frames, struct timespec *timestamp)
2001{
2002 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08002003 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07002004 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002005
Eric Laurenta1478072015-09-21 17:21:52 -07002006 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002007
Eric Laurent949a0892013-09-20 09:20:13 -07002008 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2009 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08002010 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07002011 compress_get_tstamp(out->compr, &dsp_frames,
2012 &out->sample_rate);
2013 ALOGVV("%s rendered frames %ld sample_rate %d",
2014 __func__, dsp_frames, out->sample_rate);
2015 *frames = dsp_frames;
2016 ret = 0;
2017 /* this is the best we can do */
2018 clock_gettime(CLOCK_MONOTONIC, timestamp);
2019 }
2020 } else {
2021 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002022 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002023 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2024 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002025 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002026 // This adjustment accounts for buffering after app processor.
2027 // It is based on estimated DSP latency per use case, rather than exact.
2028 signed_frames -=
2029 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2030
Eric Laurent949a0892013-09-20 09:20:13 -07002031 // It would be unusual for this value to be negative, but check just in case ...
2032 if (signed_frames >= 0) {
2033 *frames = signed_frames;
2034 ret = 0;
2035 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002036 }
2037 }
2038 }
2039
2040 pthread_mutex_unlock(&out->lock);
2041
2042 return ret;
2043}
2044
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002045static int out_set_callback(struct audio_stream_out *stream,
2046 stream_callback_t callback, void *cookie)
2047{
2048 struct stream_out *out = (struct stream_out *)stream;
2049
2050 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002051 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 out->offload_callback = callback;
2053 out->offload_cookie = cookie;
2054 pthread_mutex_unlock(&out->lock);
2055 return 0;
2056}
2057
2058static int out_pause(struct audio_stream_out* stream)
2059{
2060 struct stream_out *out = (struct stream_out *)stream;
2061 int status = -ENOSYS;
2062 ALOGV("%s", __func__);
2063 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002064 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002065 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2066 status = compress_pause(out->compr);
2067 out->offload_state = OFFLOAD_STATE_PAUSED;
2068 }
2069 pthread_mutex_unlock(&out->lock);
2070 }
2071 return status;
2072}
2073
2074static int out_resume(struct audio_stream_out* stream)
2075{
2076 struct stream_out *out = (struct stream_out *)stream;
2077 int status = -ENOSYS;
2078 ALOGV("%s", __func__);
2079 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2080 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002081 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2083 status = compress_resume(out->compr);
2084 out->offload_state = OFFLOAD_STATE_PLAYING;
2085 }
2086 pthread_mutex_unlock(&out->lock);
2087 }
2088 return status;
2089}
2090
2091static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2092{
2093 struct stream_out *out = (struct stream_out *)stream;
2094 int status = -ENOSYS;
2095 ALOGV("%s", __func__);
2096 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002097 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2099 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2100 else
2101 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2102 pthread_mutex_unlock(&out->lock);
2103 }
2104 return status;
2105}
2106
2107static int out_flush(struct audio_stream_out* stream)
2108{
2109 struct stream_out *out = (struct stream_out *)stream;
2110 ALOGV("%s", __func__);
2111 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002112 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113 stop_compressed_output_l(out);
2114 pthread_mutex_unlock(&out->lock);
2115 return 0;
2116 }
2117 return -ENOSYS;
2118}
2119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120/** audio_stream_in implementation **/
2121static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2122{
2123 struct stream_in *in = (struct stream_in *)stream;
2124
2125 return in->config.rate;
2126}
2127
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002128static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129{
2130 return -ENOSYS;
2131}
2132
2133static size_t in_get_buffer_size(const struct audio_stream *stream)
2134{
2135 struct stream_in *in = (struct stream_in *)stream;
2136
Haynes Mathew George03c40102016-01-29 17:57:48 -08002137 return in->config.period_size * in->af_period_multiplier *
2138 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139}
2140
2141static uint32_t in_get_channels(const struct audio_stream *stream)
2142{
2143 struct stream_in *in = (struct stream_in *)stream;
2144
2145 return in->channel_mask;
2146}
2147
vivek mehta4ed66e62016-04-15 23:33:34 -07002148static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149{
vivek mehta4ed66e62016-04-15 23:33:34 -07002150 struct stream_in *in = (struct stream_in *)stream;
2151 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002152}
2153
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002154static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155{
2156 return -ENOSYS;
2157}
2158
2159static int in_standby(struct audio_stream *stream)
2160{
2161 struct stream_in *in = (struct stream_in *)stream;
2162 struct audio_device *adev = in->dev;
2163 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002164 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002165
2166 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002167
2168 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002169 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002170 audio_extn_sound_trigger_stop_lab(in);
2171 in->standby = true;
2172 }
2173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002175 if (adev->adm_deregister_stream)
2176 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2177
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002178 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002180 if (in->pcm) {
2181 pcm_close(in->pcm);
2182 in->pcm = NULL;
2183 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002184 adev->enable_voicerx = false;
2185 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002187 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 }
2189 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002190 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191 return status;
2192}
2193
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002194static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002195{
2196 return 0;
2197}
2198
2199static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2200{
2201 struct stream_in *in = (struct stream_in *)stream;
2202 struct audio_device *adev = in->dev;
2203 struct str_parms *parms;
2204 char *str;
2205 char value[32];
2206 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002207 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002208
Eric Laurent994a6932013-07-17 11:51:42 -07002209 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002210 parms = str_parms_create_str(kvpairs);
2211
2212 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2213
Eric Laurenta1478072015-09-21 17:21:52 -07002214 lock_input_stream(in);
2215
Eric Laurent150dbfe2013-02-27 14:31:02 -08002216 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217 if (ret >= 0) {
2218 val = atoi(value);
2219 /* no audio source uses val == 0 */
2220 if ((in->source != val) && (val != 0)) {
2221 in->source = val;
2222 }
2223 }
2224
2225 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227 if (ret >= 0) {
2228 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002229 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230 in->device = val;
2231 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002232 if (!in->standby) {
2233 ALOGV("update input routing change");
2234 in->routing_change = true;
2235 select_devices(adev, in->usecase);
2236 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002237 }
2238 }
2239
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002240 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002241 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002242
2243 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002244 ALOGV("%s: exit: status(%d)", __func__, status);
2245 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002246}
2247
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002248static char* in_get_parameters(const struct audio_stream *stream __unused,
2249 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250{
2251 return strdup("");
2252}
2253
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002254static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255{
2256 return 0;
2257}
2258
2259static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2260 size_t bytes)
2261{
2262 struct stream_in *in = (struct stream_in *)stream;
2263 struct audio_device *adev = in->dev;
2264 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002265 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266
Eric Laurenta1478072015-09-21 17:21:52 -07002267 lock_input_stream(in);
2268
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002269 if (in->is_st_session) {
2270 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2271 /* Read from sound trigger HAL */
2272 audio_extn_sound_trigger_read(in, buffer, bytes);
2273 pthread_mutex_unlock(&in->lock);
2274 return bytes;
2275 }
2276
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002278 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002279 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002280 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002282 goto exit;
2283 }
2284 in->standby = 0;
2285 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002286
Haynes Mathew George03c40102016-01-29 17:57:48 -08002287 //what's the duration requested by the client?
2288 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2289 in->config.rate;
2290 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002291
Haynes Mathew George03c40102016-01-29 17:57:48 -08002292 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002294 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002295 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002296 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002297 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002298 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002299 if (ret < 0) {
2300 ALOGE("Failed to read w/err %s", strerror(errno));
2301 ret = -errno;
2302 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002303 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2304 if (bytes % 4 == 0) {
2305 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2306 int_buf_stream = buffer;
2307 for (size_t itt=0; itt < bytes/4 ; itt++) {
2308 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002309 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002310 } else {
2311 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2312 ret = -EINVAL;
2313 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002314 }
2315 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002316 }
2317
Haynes Mathew George03c40102016-01-29 17:57:48 -08002318 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002320 /*
2321 * Instead of writing zeroes here, we could trust the hardware
2322 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002323 * 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 -08002324 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002325 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002326 memset(buffer, 0, bytes);
2327
2328exit:
2329 pthread_mutex_unlock(&in->lock);
2330
2331 if (ret != 0) {
2332 in_standby(&in->stream.common);
2333 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002334 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002335 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002336 memset(buffer, 0, bytes); // clear return data
2337 }
2338 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002339 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002340 }
2341 return bytes;
2342}
2343
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002344static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002345{
2346 return 0;
2347}
2348
Andy Hung6ebe5962016-01-15 17:46:57 -08002349static int in_get_capture_position(const struct audio_stream_in *stream,
2350 int64_t *frames, int64_t *time)
2351{
2352 if (stream == NULL || frames == NULL || time == NULL) {
2353 return -EINVAL;
2354 }
2355 struct stream_in *in = (struct stream_in *)stream;
2356 int ret = -ENOSYS;
2357
2358 lock_input_stream(in);
2359 if (in->pcm) {
2360 struct timespec timestamp;
2361 unsigned int avail;
2362 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2363 *frames = in->frames_read + avail;
2364 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2365 ret = 0;
2366 }
2367 }
2368 pthread_mutex_unlock(&in->lock);
2369 return ret;
2370}
2371
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002372static int add_remove_audio_effect(const struct audio_stream *stream,
2373 effect_handle_t effect,
2374 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002375{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002376 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002377 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002378 int status = 0;
2379 effect_descriptor_t desc;
2380
2381 status = (*effect)->get_descriptor(effect, &desc);
2382 if (status != 0)
2383 return status;
2384
Eric Laurenta1478072015-09-21 17:21:52 -07002385 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002386 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002387 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002388 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002389 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002390 in->enable_aec != enable &&
2391 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2392 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002393 if (!enable)
2394 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002395 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2396 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2397 adev->enable_voicerx = enable;
2398 struct audio_usecase *usecase;
2399 struct listnode *node;
2400 list_for_each(node, &adev->usecase_list) {
2401 usecase = node_to_item(node, struct audio_usecase, list);
2402 if (usecase->type == PCM_PLAYBACK) {
2403 select_devices(adev, usecase->id);
2404 break;
2405 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002406 }
2407 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002408 if (!in->standby)
2409 select_devices(in->dev, in->usecase);
2410 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002411 if (in->enable_ns != enable &&
2412 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2413 in->enable_ns = enable;
2414 if (!in->standby)
2415 select_devices(in->dev, in->usecase);
2416 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002417 pthread_mutex_unlock(&in->dev->lock);
2418 pthread_mutex_unlock(&in->lock);
2419
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002420 return 0;
2421}
2422
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002423static int in_add_audio_effect(const struct audio_stream *stream,
2424 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425{
Eric Laurent994a6932013-07-17 11:51:42 -07002426 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002427 return add_remove_audio_effect(stream, effect, true);
2428}
2429
2430static int in_remove_audio_effect(const struct audio_stream *stream,
2431 effect_handle_t effect)
2432{
Eric Laurent994a6932013-07-17 11:51:42 -07002433 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002434 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435}
2436
2437static int adev_open_output_stream(struct audio_hw_device *dev,
2438 audio_io_handle_t handle,
2439 audio_devices_t devices,
2440 audio_output_flags_t flags,
2441 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002442 struct audio_stream_out **stream_out,
2443 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444{
2445 struct audio_device *adev = (struct audio_device *)dev;
2446 struct stream_out *out;
2447 int i, ret;
2448
Eric Laurent994a6932013-07-17 11:51:42 -07002449 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 __func__, config->sample_rate, config->channel_mask, devices, flags);
2451 *stream_out = NULL;
2452 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2453
2454 if (devices == AUDIO_DEVICE_NONE)
2455 devices = AUDIO_DEVICE_OUT_SPEAKER;
2456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457 out->flags = flags;
2458 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002459 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002460 out->format = config->format;
2461 out->sample_rate = config->sample_rate;
2462 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2463 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002464 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465
2466 /* Init use case and pcm_config */
2467 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002468 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002470 pthread_mutex_lock(&adev->lock);
2471 ret = read_hdmi_channel_masks(out);
2472 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002473 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002474 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002475
2476 if (config->sample_rate == 0)
2477 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2478 if (config->channel_mask == 0)
2479 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002480 if (config->format == AUDIO_FORMAT_DEFAULT)
2481 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002482
2483 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002484 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002485 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2487 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002488 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002489 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002491 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2492 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2493 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2494 ALOGE("%s: Unsupported Offload information", __func__);
2495 ret = -EINVAL;
2496 goto error_open;
2497 }
2498 if (!is_supported_format(config->offload_info.format)) {
2499 ALOGE("%s: Unsupported audio format", __func__);
2500 ret = -EINVAL;
2501 goto error_open;
2502 }
2503
2504 out->compr_config.codec = (struct snd_codec *)
2505 calloc(1, sizeof(struct snd_codec));
2506
2507 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2508 if (config->offload_info.channel_mask)
2509 out->channel_mask = config->offload_info.channel_mask;
2510 else if (config->channel_mask)
2511 out->channel_mask = config->channel_mask;
2512 out->format = config->offload_info.format;
2513 out->sample_rate = config->offload_info.sample_rate;
2514
2515 out->stream.set_callback = out_set_callback;
2516 out->stream.pause = out_pause;
2517 out->stream.resume = out_resume;
2518 out->stream.drain = out_drain;
2519 out->stream.flush = out_flush;
2520
2521 out->compr_config.codec->id =
2522 get_snd_codec_id(config->offload_info.format);
2523 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2524 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002525 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002526 out->compr_config.codec->bit_rate =
2527 config->offload_info.bit_rate;
2528 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002529 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002530 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2531
2532 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2533 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002534
2535 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002536 create_offload_callback_thread(out);
2537 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2538 __func__, config->offload_info.version,
2539 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002540 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2541 if (config->sample_rate == 0)
2542 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2543 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2544 config->sample_rate != 8000) {
2545 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2546 ret = -EINVAL;
2547 goto error_open;
2548 }
2549 out->sample_rate = config->sample_rate;
2550 out->config.rate = config->sample_rate;
2551 if (config->format == AUDIO_FORMAT_DEFAULT)
2552 config->format = AUDIO_FORMAT_PCM_16_BIT;
2553 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2554 config->format = AUDIO_FORMAT_PCM_16_BIT;
2555 ret = -EINVAL;
2556 goto error_open;
2557 }
2558 out->format = config->format;
2559 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2560 out->config = pcm_config_afe_proxy_playback;
2561 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002563 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2564 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2565 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002566 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2567 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2568 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002569 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2570 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002571 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2572 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2573 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002574 } else {
2575 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2576 out->config = pcm_config_low_latency;
2577 }
2578 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2579 if (k_enable_extended_precision
2580 && pcm_params_format_test(adev->use_case_table[out->usecase],
2581 pcm_format_from_audio_format(config->format))) {
2582 out->config.format = pcm_format_from_audio_format(config->format);
2583 /* out->format already set to config->format */
2584 } else {
2585 /* deny the externally proposed config format
2586 * and use the one specified in audio_hw layer configuration.
2587 * Note: out->format is returned by out->stream.common.get_format()
2588 * and is used to set config->format in the code several lines below.
2589 */
2590 out->format = audio_format_from_pcm_format(out->config.format);
2591 }
2592 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002593 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07002595 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
2596 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002598 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002599 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002600 adev->primary_output = out;
2601 else {
2602 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002603 ret = -EEXIST;
2604 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002605 }
2606 }
2607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 /* Check if this usecase is already existing */
2609 pthread_mutex_lock(&adev->lock);
2610 if (get_usecase_from_list(adev, out->usecase) != NULL) {
2611 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002613 ret = -EEXIST;
2614 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002615 }
2616 pthread_mutex_unlock(&adev->lock);
2617
2618 out->stream.common.get_sample_rate = out_get_sample_rate;
2619 out->stream.common.set_sample_rate = out_set_sample_rate;
2620 out->stream.common.get_buffer_size = out_get_buffer_size;
2621 out->stream.common.get_channels = out_get_channels;
2622 out->stream.common.get_format = out_get_format;
2623 out->stream.common.set_format = out_set_format;
2624 out->stream.common.standby = out_standby;
2625 out->stream.common.dump = out_dump;
2626 out->stream.common.set_parameters = out_set_parameters;
2627 out->stream.common.get_parameters = out_get_parameters;
2628 out->stream.common.add_audio_effect = out_add_audio_effect;
2629 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2630 out->stream.get_latency = out_get_latency;
2631 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002632#ifdef NO_AUDIO_OUT
2633 out->stream.write = out_write_for_no_output;
2634#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002636#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 out->stream.get_render_position = out_get_render_position;
2638 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002639 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640
Haynes Mathew George03c40102016-01-29 17:57:48 -08002641 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002643 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002644 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002646 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07002647 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002648 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2649
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 config->format = out->stream.common.get_format(&out->stream.common);
2651 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2652 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2653
2654 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002655 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002657
2658error_open:
2659 free(out);
2660 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07002661 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002662 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663}
2664
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002665static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 struct audio_stream_out *stream)
2667{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002668 struct stream_out *out = (struct stream_out *)stream;
2669 struct audio_device *adev = out->dev;
2670
Eric Laurent994a6932013-07-17 11:51:42 -07002671 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002672 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002673 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2674 destroy_offload_callback_thread(out);
2675
2676 if (out->compr_config.codec != NULL)
2677 free(out->compr_config.codec);
2678 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07002679
2680 if (adev->voice_tx_output == out)
2681 adev->voice_tx_output = NULL;
2682
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002683 pthread_cond_destroy(&out->cond);
2684 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002686 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687}
2688
2689static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2690{
2691 struct audio_device *adev = (struct audio_device *)dev;
2692 struct str_parms *parms;
2693 char *str;
2694 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002695 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002696 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07002697 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698
Joe Onorato188b6222016-03-01 11:02:27 -08002699 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002700
2701 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702
2703 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002704 status = voice_set_parameters(adev, parms);
2705 if (status != 0) {
2706 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 }
2708
2709 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
2710 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07002711 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2713 adev->bluetooth_nrec = true;
2714 else
2715 adev->bluetooth_nrec = false;
2716 }
2717
2718 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
2719 if (ret >= 0) {
2720 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2721 adev->screen_off = false;
2722 else
2723 adev->screen_off = true;
2724 }
2725
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002726 ret = str_parms_get_int(parms, "rotation", &val);
2727 if (ret >= 0) {
2728 bool reverse_speakers = false;
2729 switch(val) {
2730 // FIXME: note that the code below assumes that the speakers are in the correct placement
2731 // relative to the user when the device is rotated 90deg from its default rotation. This
2732 // assumption is device-specific, not platform-specific like this code.
2733 case 270:
2734 reverse_speakers = true;
2735 break;
2736 case 0:
2737 case 90:
2738 case 180:
2739 break;
2740 default:
2741 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07002742 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002743 }
Eric Laurent03f09432014-03-25 18:09:11 -07002744 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07002745 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002746 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002747 }
2748
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002749 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
2750 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002751 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002752 }
2753
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08002754 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002755done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002757 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07002758 ALOGV("%s: exit with code(%d)", __func__, status);
2759 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760}
2761
2762static char* adev_get_parameters(const struct audio_hw_device *dev,
2763 const char *keys)
2764{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002765 struct audio_device *adev = (struct audio_device *)dev;
2766 struct str_parms *reply = str_parms_create();
2767 struct str_parms *query = str_parms_create_str(keys);
2768 char *str;
2769
2770 pthread_mutex_lock(&adev->lock);
2771
2772 voice_get_parameters(adev, query, reply);
2773 str = str_parms_to_str(reply);
2774 str_parms_destroy(query);
2775 str_parms_destroy(reply);
2776
2777 pthread_mutex_unlock(&adev->lock);
2778 ALOGV("%s: exit: returns - %s", __func__, str);
2779 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780}
2781
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002782static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002783{
2784 return 0;
2785}
2786
Haynes Mathew George5191a852013-09-11 14:19:36 -07002787static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
2788{
2789 int ret;
2790 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002791
Eric Laurent4cc4ce12014-09-10 13:21:01 -05002792 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
2793
Haynes Mathew George5191a852013-09-11 14:19:36 -07002794 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002795 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07002796 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002797
Haynes Mathew George5191a852013-09-11 14:19:36 -07002798 return ret;
2799}
2800
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002801static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802{
2803 return -ENOSYS;
2804}
2805
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002806static int adev_get_master_volume(struct audio_hw_device *dev __unused,
2807 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808{
2809 return -ENOSYS;
2810}
2811
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002812static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002813{
2814 return -ENOSYS;
2815}
2816
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002817static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818{
2819 return -ENOSYS;
2820}
2821
2822static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2823{
2824 struct audio_device *adev = (struct audio_device *)dev;
2825
2826 pthread_mutex_lock(&adev->lock);
2827 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07002828 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002829 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07002830 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
2831 voice_is_in_call(adev)) {
2832 voice_stop_call(adev);
2833 adev->current_call_output = NULL;
2834 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835 }
2836 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002837
2838 audio_extn_extspk_set_mode(adev->extspk, mode);
2839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 return 0;
2841}
2842
2843static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2844{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002845 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847
Eric Laurent2bafff12016-03-17 12:17:23 -07002848 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002849 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002850 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002851 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00002852 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002853
2854 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002855}
2856
2857static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2858{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002859 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860 return 0;
2861}
2862
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002863static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002864 const struct audio_config *config)
2865{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002866 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002868 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
2869 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870}
2871
2872static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002873 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874 audio_devices_t devices,
2875 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002876 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07002877 audio_input_flags_t flags,
2878 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05002879 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002880{
2881 struct audio_device *adev = (struct audio_device *)dev;
2882 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002883 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002884 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002885 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886
Eric Laurent994a6932013-07-17 11:51:42 -07002887 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 *stream_in = NULL;
2889 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2890 return -EINVAL;
2891
2892 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
2893
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002894 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07002895 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 in->stream.common.get_sample_rate = in_get_sample_rate;
2898 in->stream.common.set_sample_rate = in_set_sample_rate;
2899 in->stream.common.get_buffer_size = in_get_buffer_size;
2900 in->stream.common.get_channels = in_get_channels;
2901 in->stream.common.get_format = in_get_format;
2902 in->stream.common.set_format = in_set_format;
2903 in->stream.common.standby = in_standby;
2904 in->stream.common.dump = in_dump;
2905 in->stream.common.set_parameters = in_set_parameters;
2906 in->stream.common.get_parameters = in_get_parameters;
2907 in->stream.common.add_audio_effect = in_add_audio_effect;
2908 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2909 in->stream.set_gain = in_set_gain;
2910 in->stream.read = in_read;
2911 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08002912 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002913
2914 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002915 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002916 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002917 in->standby = 1;
2918 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002919 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002920 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002921
vivek mehta57ff9b52016-04-28 14:13:08 -07002922 // restrict 24 bit capture for unprocessed source only
2923 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
2924 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07002925 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07002926 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
2927 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
2928 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
2929 bool ret_error = false;
2930 /* 24 bit is restricted to UNPROCESSED source only,also format supported
2931 from HAL is 8_24
2932 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
2933 8_24 return error indicating supported format is 8_24
2934 *> In case of any other source requesting 24 bit or float return error
2935 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07002936
vivek mehta57ff9b52016-04-28 14:13:08 -07002937 on error flinger will retry with supported format passed
2938 */
2939 if (source != AUDIO_SOURCE_UNPROCESSED) {
2940 config->format = AUDIO_FORMAT_PCM_16_BIT;
2941 ret_error = true;
2942 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
2943 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
2944 ret_error = true;
2945 }
2946
2947 if (ret_error) {
2948 ret = -EINVAL;
2949 goto err_open;
2950 }
vivek mehta4ed66e62016-04-15 23:33:34 -07002951 }
2952
vivek mehta57ff9b52016-04-28 14:13:08 -07002953 in->format = config->format;
2954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002956 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
2957 if (config->sample_rate == 0)
2958 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2959 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2960 config->sample_rate != 8000) {
2961 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2962 ret = -EINVAL;
2963 goto err_open;
2964 }
vivek mehta4ed66e62016-04-15 23:33:34 -07002965
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002966 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2967 config->format = AUDIO_FORMAT_PCM_16_BIT;
2968 ret = -EINVAL;
2969 goto err_open;
2970 }
2971
2972 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
2973 in->config = pcm_config_afe_proxy_record;
2974 } else {
2975 in->usecase = USECASE_AUDIO_RECORD;
2976 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
2977 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
2978 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07002979#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002980 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07002981#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08002982 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002983 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002984
Haynes Mathew George03c40102016-01-29 17:57:48 -08002985 in->config = in->realtime ? pcm_config_audio_capture_rt :
2986 pcm_config_audio_capture;
2987
vivek mehta4ed66e62016-04-15 23:33:34 -07002988 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
2989 in->config.format = PCM_FORMAT_S24_LE;
2990
Haynes Mathew George03c40102016-01-29 17:57:48 -08002991 if (!in->realtime) {
2992 frame_size = audio_stream_in_frame_size(&in->stream);
2993 buffer_size = get_input_buffer_size(config->sample_rate,
2994 config->format,
2995 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002996 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08002997 in->config.period_size = buffer_size / frame_size;
2998 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002999 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08003000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003002 if (in->realtime) {
3003 in->af_period_multiplier = af_period_multiplier;
3004 } else {
3005 in->config.rate = config->sample_rate;
3006 in->af_period_multiplier = 1;
3007 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003009 /* This stream could be for sound trigger lab,
3010 get sound trigger pcm if present */
3011 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012
3013 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003014 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 return 0;
3016
3017err_open:
3018 free(in);
3019 *stream_in = NULL;
3020 return ret;
3021}
3022
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003023static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 struct audio_stream_in *stream)
3025{
Eric Laurent994a6932013-07-17 11:51:42 -07003026 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 in_standby(&stream->common);
3029 free(stream);
3030
3031 return;
3032}
3033
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003034static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035{
3036 return 0;
3037}
3038
Andy Hung31aca912014-03-20 17:14:59 -07003039/* verifies input and output devices and their capabilities.
3040 *
3041 * This verification is required when enabling extended bit-depth or
3042 * sampling rates, as not all qcom products support it.
3043 *
3044 * Suitable for calling only on initialization such as adev_open().
3045 * It fills the audio_device use_case_table[] array.
3046 *
3047 * Has a side-effect that it needs to configure audio routing / devices
3048 * in order to power up the devices and read the device parameters.
3049 * It does not acquire any hw device lock. Should restore the devices
3050 * back to "normal state" upon completion.
3051 */
3052static int adev_verify_devices(struct audio_device *adev)
3053{
3054 /* enumeration is a bit difficult because one really wants to pull
3055 * the use_case, device id, etc from the hidden pcm_device_table[].
3056 * In this case there are the following use cases and device ids.
3057 *
3058 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3059 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3060 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3061 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3062 * [USECASE_AUDIO_RECORD] = {0, 0},
3063 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3064 * [USECASE_VOICE_CALL] = {2, 2},
3065 *
3066 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3067 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3068 */
3069
3070 /* should be the usecases enabled in adev_open_input_stream() */
3071 static const int test_in_usecases[] = {
3072 USECASE_AUDIO_RECORD,
3073 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3074 };
3075 /* should be the usecases enabled in adev_open_output_stream()*/
3076 static const int test_out_usecases[] = {
3077 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3078 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3079 };
3080 static const usecase_type_t usecase_type_by_dir[] = {
3081 PCM_PLAYBACK,
3082 PCM_CAPTURE,
3083 };
3084 static const unsigned flags_by_dir[] = {
3085 PCM_OUT,
3086 PCM_IN,
3087 };
3088
3089 size_t i;
3090 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003091 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003092 char info[512]; /* for possible debug info */
3093
3094 for (dir = 0; dir < 2; ++dir) {
3095 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3096 const unsigned flags_dir = flags_by_dir[dir];
3097 const size_t testsize =
3098 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3099 const int *testcases =
3100 dir ? test_in_usecases : test_out_usecases;
3101 const audio_devices_t audio_device =
3102 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3103
3104 for (i = 0; i < testsize; ++i) {
3105 const audio_usecase_t audio_usecase = testcases[i];
3106 int device_id;
3107 snd_device_t snd_device;
3108 struct pcm_params **pparams;
3109 struct stream_out out;
3110 struct stream_in in;
3111 struct audio_usecase uc_info;
3112 int retval;
3113
3114 pparams = &adev->use_case_table[audio_usecase];
3115 pcm_params_free(*pparams); /* can accept null input */
3116 *pparams = NULL;
3117
3118 /* find the device ID for the use case (signed, for error) */
3119 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3120 if (device_id < 0)
3121 continue;
3122
3123 /* prepare structures for device probing */
3124 memset(&uc_info, 0, sizeof(uc_info));
3125 uc_info.id = audio_usecase;
3126 uc_info.type = usecase_type;
3127 if (dir) {
3128 adev->active_input = &in;
3129 memset(&in, 0, sizeof(in));
3130 in.device = audio_device;
3131 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3132 uc_info.stream.in = &in;
3133 } else {
3134 adev->active_input = NULL;
3135 }
3136 memset(&out, 0, sizeof(out));
3137 out.devices = audio_device; /* only field needed in select_devices */
3138 uc_info.stream.out = &out;
3139 uc_info.devices = audio_device;
3140 uc_info.in_snd_device = SND_DEVICE_NONE;
3141 uc_info.out_snd_device = SND_DEVICE_NONE;
3142 list_add_tail(&adev->usecase_list, &uc_info.list);
3143
3144 /* select device - similar to start_(in/out)put_stream() */
3145 retval = select_devices(adev, audio_usecase);
3146 if (retval >= 0) {
3147 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3148#if LOG_NDEBUG == 0
3149 if (*pparams) {
3150 ALOGV("%s: (%s) card %d device %d", __func__,
3151 dir ? "input" : "output", card_id, device_id);
3152 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003153 } else {
3154 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3155 }
3156#endif
3157 }
3158
3159 /* deselect device - similar to stop_(in/out)put_stream() */
3160 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003161 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003162 /* 2. Disable the rx device */
3163 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003164 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003165 list_remove(&uc_info.list);
3166 }
3167 }
3168 adev->active_input = NULL; /* restore adev state */
3169 return 0;
3170}
3171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003172static int adev_close(hw_device_t *device)
3173{
Andy Hung31aca912014-03-20 17:14:59 -07003174 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003176
3177 if (!adev)
3178 return 0;
3179
3180 pthread_mutex_lock(&adev_init_lock);
3181
3182 if ((--audio_device_ref_count) == 0) {
3183 audio_route_free(adev->audio_route);
3184 free(adev->snd_dev_ref_cnt);
3185 platform_deinit(adev->platform);
3186 audio_extn_extspk_deinit(adev->extspk);
3187 audio_extn_sound_trigger_deinit(adev);
3188 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3189 pcm_params_free(adev->use_case_table[i]);
3190 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003191 if (adev->adm_deinit)
3192 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003193 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003194 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003195
3196 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003197
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003198 return 0;
3199}
3200
Glenn Kasten4f993392014-05-14 07:30:48 -07003201/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3202 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3203 * just that it _might_ work.
3204 */
3205static int period_size_is_plausible_for_low_latency(int period_size)
3206{
3207 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003208 case 48:
3209 case 96:
3210 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003211 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003212 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003213 case 240:
3214 case 320:
3215 case 480:
3216 return 1;
3217 default:
3218 return 0;
3219 }
3220}
3221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222static int adev_open(const hw_module_t *module, const char *name,
3223 hw_device_t **device)
3224{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003225 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003226
Eric Laurent2bafff12016-03-17 12:17:23 -07003227 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003228 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003229 pthread_mutex_lock(&adev_init_lock);
3230 if (audio_device_ref_count != 0) {
3231 *device = &adev->device.common;
3232 audio_device_ref_count++;
3233 ALOGV("%s: returning existing instance of adev", __func__);
3234 ALOGV("%s: exit", __func__);
3235 pthread_mutex_unlock(&adev_init_lock);
3236 return 0;
3237 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003238 adev = calloc(1, sizeof(struct audio_device));
3239
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003240 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3243 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3244 adev->device.common.module = (struct hw_module_t *)module;
3245 adev->device.common.close = adev_close;
3246
3247 adev->device.init_check = adev_init_check;
3248 adev->device.set_voice_volume = adev_set_voice_volume;
3249 adev->device.set_master_volume = adev_set_master_volume;
3250 adev->device.get_master_volume = adev_get_master_volume;
3251 adev->device.set_master_mute = adev_set_master_mute;
3252 adev->device.get_master_mute = adev_get_master_mute;
3253 adev->device.set_mode = adev_set_mode;
3254 adev->device.set_mic_mute = adev_set_mic_mute;
3255 adev->device.get_mic_mute = adev_get_mic_mute;
3256 adev->device.set_parameters = adev_set_parameters;
3257 adev->device.get_parameters = adev_get_parameters;
3258 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3259 adev->device.open_output_stream = adev_open_output_stream;
3260 adev->device.close_output_stream = adev_close_output_stream;
3261 adev->device.open_input_stream = adev_open_input_stream;
3262 adev->device.close_input_stream = adev_close_input_stream;
3263 adev->device.dump = adev_dump;
3264
3265 /* Set the default route before the PCM stream is opened */
3266 pthread_mutex_lock(&adev->lock);
3267 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003268 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003269 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003270 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003271 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003272 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003273 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003274 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003275 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003276 pthread_mutex_unlock(&adev->lock);
3277
3278 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003279 adev->platform = platform_init(adev);
3280 if (!adev->platform) {
3281 free(adev->snd_dev_ref_cnt);
3282 free(adev);
3283 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3284 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003285 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003286 return -EINVAL;
3287 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003288
Eric Laurent0499d4f2014-08-25 22:39:29 -05003289 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003290 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003291
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003292 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3293 if (adev->visualizer_lib == NULL) {
3294 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3295 } else {
3296 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3297 adev->visualizer_start_output =
3298 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3299 "visualizer_hal_start_output");
3300 adev->visualizer_stop_output =
3301 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3302 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003303 }
3304
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003305 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3306 if (adev->offload_effects_lib == NULL) {
3307 ALOGW("%s: DLOPEN failed for %s", __func__,
3308 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3309 } else {
3310 ALOGV("%s: DLOPEN successful for %s", __func__,
3311 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3312 adev->offload_effects_start_output =
3313 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3314 "offload_effects_bundle_hal_start_output");
3315 adev->offload_effects_stop_output =
3316 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3317 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003318 }
3319
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003320 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3321 if (adev->adm_lib == NULL) {
3322 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3323 } else {
3324 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3325 adev->adm_init = (adm_init_t)
3326 dlsym(adev->adm_lib, "adm_init");
3327 adev->adm_deinit = (adm_deinit_t)
3328 dlsym(adev->adm_lib, "adm_deinit");
3329 adev->adm_register_input_stream = (adm_register_input_stream_t)
3330 dlsym(adev->adm_lib, "adm_register_input_stream");
3331 adev->adm_register_output_stream = (adm_register_output_stream_t)
3332 dlsym(adev->adm_lib, "adm_register_output_stream");
3333 adev->adm_deregister_stream = (adm_deregister_stream_t)
3334 dlsym(adev->adm_lib, "adm_deregister_stream");
3335 adev->adm_request_focus = (adm_request_focus_t)
3336 dlsym(adev->adm_lib, "adm_request_focus");
3337 adev->adm_abandon_focus = (adm_abandon_focus_t)
3338 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003339 adev->adm_set_config = (adm_set_config_t)
3340 dlsym(adev->adm_lib, "adm_set_config");
3341 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3342 dlsym(adev->adm_lib, "adm_request_focus_v2");
3343 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3344 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3345 adev->adm_on_routing_change = (adm_on_routing_change_t)
3346 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003347 }
3348
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003349 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003350 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003353
Andy Hung31aca912014-03-20 17:14:59 -07003354 if (k_enable_extended_precision)
3355 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356
Glenn Kasten4f993392014-05-14 07:30:48 -07003357 char value[PROPERTY_VALUE_MAX];
3358 int trial;
3359 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3360 trial = atoi(value);
3361 if (period_size_is_plausible_for_low_latency(trial)) {
3362 pcm_config_low_latency.period_size = trial;
3363 pcm_config_low_latency.start_threshold = trial / 4;
3364 pcm_config_low_latency.avail_min = trial / 4;
3365 configured_low_latency_capture_period_size = trial;
3366 }
3367 }
3368 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3369 trial = atoi(value);
3370 if (period_size_is_plausible_for_low_latency(trial)) {
3371 configured_low_latency_capture_period_size = trial;
3372 }
3373 }
3374
vivek mehta1a9b7c02015-06-25 11:49:38 -07003375 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003376
3377 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3378 af_period_multiplier = atoi(value);
3379 if (af_period_multiplier < 0) {
3380 af_period_multiplier = 2;
3381 } else if (af_period_multiplier > 4) {
3382 af_period_multiplier = 4;
3383 }
3384 ALOGV("new period_multiplier = %d", af_period_multiplier);
3385 }
3386
vivek mehta1a9b7c02015-06-25 11:49:38 -07003387 pthread_mutex_unlock(&adev_init_lock);
3388
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003389 if (adev->adm_init)
3390 adev->adm_data = adev->adm_init();
3391
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003392 audio_extn_perf_lock_init();
3393
Eric Laurent2bafff12016-03-17 12:17:23 -07003394 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395 return 0;
3396}
3397
3398static struct hw_module_methods_t hal_module_methods = {
3399 .open = adev_open,
3400};
3401
3402struct audio_module HAL_MODULE_INFO_SYM = {
3403 .common = {
3404 .tag = HARDWARE_MODULE_TAG,
3405 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3406 .hal_api_version = HARDWARE_HAL_API_VERSION,
3407 .id = AUDIO_HARDWARE_MODULE_ID,
3408 .name = "QCOM Audio HAL",
3409 .author = "Code Aurora Forum",
3410 .methods = &hal_module_methods,
3411 },
3412};