blob: 911a49cfa14574d977faf277def470e790f9d704 [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
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700372static bool is_supported_format(audio_format_t format)
373{
Eric Laurent8251ac82014-07-23 11:00:25 -0700374 switch (format) {
375 case AUDIO_FORMAT_MP3:
376 case AUDIO_FORMAT_AAC_LC:
377 case AUDIO_FORMAT_AAC_HE_V1:
378 case AUDIO_FORMAT_AAC_HE_V2:
379 return true;
380 default:
381 break;
382 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700383 return false;
384}
385
Haynes Mathew George03c40102016-01-29 17:57:48 -0800386static inline bool is_mmap_usecase(audio_usecase_t uc_id)
387{
388 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
389 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
390}
391
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700392static int get_snd_codec_id(audio_format_t format)
393{
394 int id = 0;
395
Eric Laurent8251ac82014-07-23 11:00:25 -0700396 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700397 case AUDIO_FORMAT_MP3:
398 id = SND_AUDIOCODEC_MP3;
399 break;
400 case AUDIO_FORMAT_AAC:
401 id = SND_AUDIOCODEC_AAC;
402 break;
403 default:
404 ALOGE("%s: Unsupported audio format", __func__);
405 }
406
407 return id;
408}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800409
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800410int enable_audio_route(struct audio_device *adev,
411 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800412{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700413 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800414 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800415
416 if (usecase == NULL)
417 return -EINVAL;
418
419 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
420
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800421 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700422 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800423 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700424 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800425
426 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500427 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Joe Onorato188b6222016-03-01 11:02:27 -0800428 ALOGV("%s: apply and update mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700429 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800431 ALOGV("%s: exit", __func__);
432 return 0;
433}
434
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800435int disable_audio_route(struct audio_device *adev,
436 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700438 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800439 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800440
441 if (usecase == NULL)
442 return -EINVAL;
443
444 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700445 if (usecase->type == PCM_CAPTURE)
446 snd_device = usecase->in_snd_device;
447 else
448 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800449 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500450 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Joe Onorato188b6222016-03-01 11:02:27 -0800451 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700452 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800453
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800454 ALOGV("%s: exit", __func__);
455 return 0;
456}
457
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800458int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700459 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800460{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700461 int i, num_devices = 0;
462 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800463 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800464 if (snd_device < SND_DEVICE_MIN ||
465 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800466 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800467 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800468 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700469
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700470 platform_send_audio_calibration(adev->platform, snd_device);
471
vivek mehtade4849c2016-03-03 17:23:38 -0800472 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700473 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700474 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800475 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700476 }
477
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700478 /* due to the possibility of calibration overwrite between listen
479 and audio, notify sound trigger hal before audio calibration is sent */
480 audio_extn_sound_trigger_update_device_status(snd_device,
481 ST_EVENT_SND_DEVICE_BUSY);
482
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700483 if (audio_extn_spkr_prot_is_enabled())
484 audio_extn_spkr_prot_calib_cancel(adev);
485
zhaoyang yin4211fad2015-06-04 21:13:25 +0800486 audio_extn_dsm_feedback_enable(adev, snd_device, true);
487
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700488 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
489 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
490 audio_extn_spkr_prot_is_enabled()) {
491 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800492 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700493 }
494 if (audio_extn_spkr_prot_start_processing(snd_device)) {
495 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800496 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700497 }
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700498 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
499 for (i = 0; i < num_devices; i++) {
500 enable_snd_device(adev, new_snd_devices[i]);
501 }
vivek mehtab6506412015-08-07 16:55:17 -0700502 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700503 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800504 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
505 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
506 ALOGE(" %s: Invalid sound device returned", __func__);
507 goto on_error;
508 }
Ed Tam70b5c142016-03-21 19:14:29 -0700509
vivek mehtade4849c2016-03-03 17:23:38 -0800510 ALOGV("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
511 audio_route_apply_and_update_path(adev->audio_route, device_name);
512 }
513on_success:
514 adev->snd_dev_ref_cnt[snd_device]++;
515 ret_val = 0;
516on_error:
517 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800518}
519
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800520int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700521 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800522{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700523 int i, num_devices = 0;
524 snd_device_t new_snd_devices[2];
525
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800526 if (snd_device < SND_DEVICE_MIN ||
527 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800528 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800529 return -EINVAL;
530 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700531 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
532 ALOGE("%s: device ref cnt is already 0", __func__);
533 return -EINVAL;
534 }
535 adev->snd_dev_ref_cnt[snd_device]--;
536 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800537 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700538 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
539 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
540 audio_extn_spkr_prot_is_enabled()) {
541 audio_extn_spkr_prot_stop_processing(snd_device);
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700542 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
543 for (i = 0; i < num_devices; i++) {
544 disable_snd_device(adev, new_snd_devices[i]);
545 }
vivek mehtab6506412015-08-07 16:55:17 -0700546 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700547 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800548 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
549 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
550 ALOGE(" %s: Invalid sound device returned", __func__);
551 return -EINVAL;
552 }
553
554 ALOGV("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
555 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700556 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700557 audio_extn_sound_trigger_update_device_status(snd_device,
558 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700559 }
vivek mehtab6506412015-08-07 16:55:17 -0700560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561 return 0;
562}
563
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700564static void check_and_route_playback_usecases(struct audio_device *adev,
565 struct audio_usecase *uc_info,
566 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700567{
568 struct listnode *node;
569 struct audio_usecase *usecase;
570 bool switch_device[AUDIO_USECASE_MAX];
571 int i, num_uc_to_switch = 0;
572
573 /*
574 * This function is to make sure that all the usecases that are active on
575 * the hardware codec backend are always routed to any one device that is
576 * handled by the hardware codec.
577 * For example, if low-latency and deep-buffer usecases are currently active
578 * on speaker and out_set_parameters(headset) is received on low-latency
579 * output, then we have to make sure deep-buffer is also switched to headset,
580 * because of the limitation that both the devices cannot be enabled
581 * at the same time as they share the same backend.
582 */
583 /* Disable all the usecases on the shared backend other than the
584 specified usecase */
585 for (i = 0; i < AUDIO_USECASE_MAX; i++)
586 switch_device[i] = false;
587
588 list_for_each(node, &adev->usecase_list) {
589 usecase = node_to_item(node, struct audio_usecase, list);
590 if (usecase->type != PCM_CAPTURE &&
591 usecase != uc_info &&
592 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700593 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
594 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700595 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
596 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700597 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700598 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700599 switch_device[usecase->id] = true;
600 num_uc_to_switch++;
601 }
602 }
603
604 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700605 list_for_each(node, &adev->usecase_list) {
606 usecase = node_to_item(node, struct audio_usecase, list);
607 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700608 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900609 }
610 }
611
612 list_for_each(node, &adev->usecase_list) {
613 usecase = node_to_item(node, struct audio_usecase, list);
614 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700615 enable_snd_device(adev, snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 }
617 }
618
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619 /* Re-route all the usecases on the shared backend other than the
620 specified usecase to new snd devices */
621 list_for_each(node, &adev->usecase_list) {
622 usecase = node_to_item(node, struct audio_usecase, list);
623 /* Update the out_snd_device only before enabling the audio route */
624 if (switch_device[usecase->id] ) {
625 usecase->out_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700626 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700627 }
628 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700629 }
630}
631
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700632static void check_and_route_capture_usecases(struct audio_device *adev,
633 struct audio_usecase *uc_info,
634 snd_device_t snd_device)
635{
636 struct listnode *node;
637 struct audio_usecase *usecase;
638 bool switch_device[AUDIO_USECASE_MAX];
639 int i, num_uc_to_switch = 0;
640
vivek mehta4ed66e62016-04-15 23:33:34 -0700641 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
642
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700643 /*
644 * This function is to make sure that all the active capture usecases
645 * are always routed to the same input sound device.
646 * For example, if audio-record and voice-call usecases are currently
647 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
648 * is received for voice call then we have to make sure that audio-record
649 * usecase is also switched to earpiece i.e. voice-dmic-ef,
650 * because of the limitation that two devices cannot be enabled
651 * at the same time if they share the same backend.
652 */
653 for (i = 0; i < AUDIO_USECASE_MAX; i++)
654 switch_device[i] = false;
655
656 list_for_each(node, &adev->usecase_list) {
657 usecase = node_to_item(node, struct audio_usecase, list);
658 if (usecase->type != PCM_PLAYBACK &&
659 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700660 usecase->in_snd_device != snd_device &&
661 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700662 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
663 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700664 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700665 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700666 switch_device[usecase->id] = true;
667 num_uc_to_switch++;
668 }
669 }
670
671 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700672 list_for_each(node, &adev->usecase_list) {
673 usecase = node_to_item(node, struct audio_usecase, list);
674 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700675 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700676 }
677 }
678
679 list_for_each(node, &adev->usecase_list) {
680 usecase = node_to_item(node, struct audio_usecase, list);
681 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700682 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700683 }
684 }
685
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700686 /* Re-route all the usecases on the shared backend other than the
687 specified usecase to new snd devices */
688 list_for_each(node, &adev->usecase_list) {
689 usecase = node_to_item(node, struct audio_usecase, list);
690 /* Update the in_snd_device only before enabling the audio route */
691 if (switch_device[usecase->id] ) {
692 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700693 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700694 }
695 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700696 }
697}
698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800699/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700700static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800701{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700702 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700703 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800704
705 switch (channels) {
706 /*
707 * Do not handle stereo output in Multi-channel cases
708 * Stereo case is handled in normal playback path
709 */
710 case 6:
711 ALOGV("%s: HDMI supports 5.1", __func__);
712 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
713 break;
714 case 8:
715 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
716 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
717 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
718 break;
719 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700720 ALOGE("HDMI does not support multi channel playback");
721 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800722 break;
723 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700724 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800725}
726
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700727static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
728{
729 struct audio_usecase *usecase;
730 struct listnode *node;
731
732 list_for_each(node, &adev->usecase_list) {
733 usecase = node_to_item(node, struct audio_usecase, list);
734 if (usecase->type == VOICE_CALL) {
735 ALOGV("%s: usecase id %d", __func__, usecase->id);
736 return usecase->id;
737 }
738 }
739 return USECASE_INVALID;
740}
741
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800742struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
743 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700744{
745 struct audio_usecase *usecase;
746 struct listnode *node;
747
748 list_for_each(node, &adev->usecase_list) {
749 usecase = node_to_item(node, struct audio_usecase, list);
750 if (usecase->id == uc_id)
751 return usecase;
752 }
753 return NULL;
754}
755
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800756int select_devices(struct audio_device *adev,
757 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800758{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800759 snd_device_t out_snd_device = SND_DEVICE_NONE;
760 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700761 struct audio_usecase *usecase = NULL;
762 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800763 struct audio_usecase *hfp_usecase = NULL;
764 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800765 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700766 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800767
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700768 usecase = get_usecase_from_list(adev, uc_id);
769 if (usecase == NULL) {
770 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
771 return -EINVAL;
772 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800773
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800774 if ((usecase->type == VOICE_CALL) ||
775 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700776 out_snd_device = platform_get_output_snd_device(adev->platform,
777 usecase->stream.out->devices);
778 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700779 usecase->devices = usecase->stream.out->devices;
780 } else {
781 /*
782 * If the voice call is active, use the sound devices of voice call usecase
783 * so that it would not result any device switch. All the usecases will
784 * be switched to new device when select_devices() is called for voice call
785 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700786 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700787 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700788 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700789 vc_usecase = get_usecase_from_list(adev,
790 get_voice_usecase_id_from_list(adev));
791 if ((vc_usecase != NULL) &&
792 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
793 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700794 in_snd_device = vc_usecase->in_snd_device;
795 out_snd_device = vc_usecase->out_snd_device;
796 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800797 } else if (audio_extn_hfp_is_active(adev)) {
798 hfp_ucid = audio_extn_hfp_get_usecase();
799 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
800 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
801 in_snd_device = hfp_usecase->in_snd_device;
802 out_snd_device = hfp_usecase->out_snd_device;
803 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700804 }
805 if (usecase->type == PCM_PLAYBACK) {
806 usecase->devices = usecase->stream.out->devices;
807 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700808 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700809 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700810 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700811 if (usecase->stream.out == adev->primary_output &&
812 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -0700813 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
814 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800815 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700816 select_devices(adev, adev->active_input->usecase);
817 }
818 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700819 } else if (usecase->type == PCM_CAPTURE) {
820 usecase->devices = usecase->stream.in->device;
821 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700822 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700823 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -0700824 if (adev->active_input &&
825 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
826 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800827 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -0700828 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
829 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
830 } else if (adev->primary_output) {
831 out_device = adev->primary_output->devices;
832 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700833 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700834 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700835 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700836 }
837 }
838
839 if (out_snd_device == usecase->out_snd_device &&
840 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800841 return 0;
842 }
843
Eric Laurent2bafff12016-03-17 12:17:23 -0700844 if (out_snd_device != SND_DEVICE_NONE &&
845 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
846 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
847 __func__,
848 use_case_table[uc_id],
849 adev->last_logged_snd_device[uc_id][0],
850 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
851 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
852 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
853 -1,
854 out_snd_device,
855 platform_get_snd_device_name(out_snd_device),
856 platform_get_snd_device_acdb_id(out_snd_device));
857 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
858 }
859 if (in_snd_device != SND_DEVICE_NONE &&
860 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
861 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
862 __func__,
863 use_case_table[uc_id],
864 adev->last_logged_snd_device[uc_id][1],
865 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
866 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
867 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
868 -1,
869 in_snd_device,
870 platform_get_snd_device_name(in_snd_device),
871 platform_get_snd_device_acdb_id(in_snd_device));
872 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
873 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800874
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800875 /*
876 * Limitation: While in call, to do a device switch we need to disable
877 * and enable both RX and TX devices though one of them is same as current
878 * device.
879 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700880 if ((usecase->type == VOICE_CALL) &&
881 (usecase->in_snd_device != SND_DEVICE_NONE) &&
882 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700883 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -0700884 /* Disable sidetone only if voice call already exists */
885 if (voice_is_call_state_active(adev))
886 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800887 }
888
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700889 /* Disable current sound devices */
890 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700891 disable_audio_route(adev, usecase);
892 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800893 }
894
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700895 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700896 disable_audio_route(adev, usecase);
897 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800898 }
899
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700900 /* Applicable only on the targets that has external modem.
901 * New device information should be sent to modem before enabling
902 * the devices to reduce in-call device switch time.
903 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700904 if ((usecase->type == VOICE_CALL) &&
905 (usecase->in_snd_device != SND_DEVICE_NONE) &&
906 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700907 status = platform_switch_voice_call_enable_device_config(adev->platform,
908 out_snd_device,
909 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700910 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700911
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700912 /* Enable new sound devices */
913 if (out_snd_device != SND_DEVICE_NONE) {
914 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700915 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700916 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800917 }
918
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700919 if (in_snd_device != SND_DEVICE_NONE) {
920 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700921 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700922 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700923
Eric Laurentb23d5282013-05-14 15:27:20 -0700924 if (usecase->type == VOICE_CALL)
925 status = platform_switch_voice_call_device_post(adev->platform,
926 out_snd_device,
927 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800928
sangwoo170731f2013-06-08 15:36:36 +0900929 usecase->in_snd_device = in_snd_device;
930 usecase->out_snd_device = out_snd_device;
931
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700932 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900933
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700934 /* Applicable only on the targets that has external modem.
935 * Enable device command should be sent to modem only after
936 * enabling voice call mixer controls
937 */
vivek mehta765eb642015-08-07 19:46:06 -0700938 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700939 status = platform_switch_voice_call_usecase_route_post(adev->platform,
940 out_snd_device,
941 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -0700942 /* Enable sidetone only if voice call already exists */
943 if (voice_is_call_state_active(adev))
944 voice_set_sidetone(adev, out_snd_device, true);
945 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700946
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800947 return status;
948}
949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800950static int stop_input_stream(struct stream_in *in)
951{
952 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800953 struct audio_usecase *uc_info;
954 struct audio_device *adev = in->dev;
955
Eric Laurentc8400632013-02-14 19:04:54 -0800956 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800957
Eric Laurent994a6932013-07-17 11:51:42 -0700958 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700959 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800960 uc_info = get_usecase_from_list(adev, in->usecase);
961 if (uc_info == NULL) {
962 ALOGE("%s: Could not find the usecase (%d) in the list",
963 __func__, in->usecase);
964 return -EINVAL;
965 }
966
Eric Laurent150dbfe2013-02-27 14:31:02 -0800967 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700968 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700969
970 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700971 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800972
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800973 list_remove(&uc_info->list);
974 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800975
Eric Laurent994a6932013-07-17 11:51:42 -0700976 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977 return ret;
978}
979
980int start_input_stream(struct stream_in *in)
981{
982 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800983 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800984 struct audio_usecase *uc_info;
985 struct audio_device *adev = in->dev;
986
Eric Laurent994a6932013-07-17 11:51:42 -0700987 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Eric Laurentb23d5282013-05-14 15:27:20 -0700988 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800989 if (in->pcm_device_id < 0) {
990 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
991 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800992 ret = -EINVAL;
993 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800994 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700995
996 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800997 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
998 uc_info->id = in->usecase;
999 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001000 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001 uc_info->devices = in->device;
1002 uc_info->in_snd_device = SND_DEVICE_NONE;
1003 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001004
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001005 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001006
1007 audio_extn_perf_lock_acquire();
1008
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001009 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001010
Eric Laurentc8400632013-02-14 19:04:54 -08001011 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001012 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001013
Andy Hung6ebe5962016-01-15 17:46:57 -08001014 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001015 unsigned int pcm_open_retry_count = 0;
1016
1017 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1018 flags |= PCM_MMAP | PCM_NOIRQ;
1019 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001020 } else if (in->realtime) {
1021 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001023
1024 while (1) {
1025 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1026 flags, &in->config);
1027 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1028 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1029 if (in->pcm != NULL) {
1030 pcm_close(in->pcm);
1031 in->pcm = NULL;
1032 }
1033 if (pcm_open_retry_count-- == 0) {
1034 ret = -EIO;
1035 goto error_open;
1036 }
1037 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1038 continue;
1039 }
1040 break;
1041 }
1042
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001043 ALOGV("%s: pcm_prepare", __func__);
1044 ret = pcm_prepare(in->pcm);
1045 if (ret < 0) {
1046 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1047 pcm_close(in->pcm);
1048 in->pcm = NULL;
1049 goto error_open;
1050 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001051 register_in_stream(in);
1052 if (in->realtime) {
1053 ret = pcm_start(in->pcm);
1054 }
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001055 audio_extn_perf_lock_release();
1056
Eric Laurent994a6932013-07-17 11:51:42 -07001057 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001058
Eric Laurentc8400632013-02-14 19:04:54 -08001059 return ret;
1060
1061error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001063 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001064
1065error_config:
1066 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001067 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001068
1069 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070}
1071
Eric Laurenta1478072015-09-21 17:21:52 -07001072void lock_input_stream(struct stream_in *in)
1073{
1074 pthread_mutex_lock(&in->pre_lock);
1075 pthread_mutex_lock(&in->lock);
1076 pthread_mutex_unlock(&in->pre_lock);
1077}
1078
1079void lock_output_stream(struct stream_out *out)
1080{
1081 pthread_mutex_lock(&out->pre_lock);
1082 pthread_mutex_lock(&out->lock);
1083 pthread_mutex_unlock(&out->pre_lock);
1084}
1085
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001086/* must be called with out->lock locked */
1087static int send_offload_cmd_l(struct stream_out* out, int command)
1088{
1089 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1090
1091 ALOGVV("%s %d", __func__, command);
1092
1093 cmd->cmd = command;
1094 list_add_tail(&out->offload_cmd_list, &cmd->node);
1095 pthread_cond_signal(&out->offload_cond);
1096 return 0;
1097}
1098
1099/* must be called iwth out->lock locked */
1100static void stop_compressed_output_l(struct stream_out *out)
1101{
1102 out->offload_state = OFFLOAD_STATE_IDLE;
1103 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001104 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001105 if (out->compr != NULL) {
1106 compress_stop(out->compr);
1107 while (out->offload_thread_blocked) {
1108 pthread_cond_wait(&out->cond, &out->lock);
1109 }
1110 }
1111}
1112
1113static void *offload_thread_loop(void *context)
1114{
1115 struct stream_out *out = (struct stream_out *) context;
1116 struct listnode *item;
1117
1118 out->offload_state = OFFLOAD_STATE_IDLE;
1119 out->playback_started = 0;
1120
1121 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1122 set_sched_policy(0, SP_FOREGROUND);
1123 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1124
1125 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001126 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001127 for (;;) {
1128 struct offload_cmd *cmd = NULL;
1129 stream_callback_event_t event;
1130 bool send_callback = false;
1131
1132 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1133 __func__, list_empty(&out->offload_cmd_list),
1134 out->offload_state);
1135 if (list_empty(&out->offload_cmd_list)) {
1136 ALOGV("%s SLEEPING", __func__);
1137 pthread_cond_wait(&out->offload_cond, &out->lock);
1138 ALOGV("%s RUNNING", __func__);
1139 continue;
1140 }
1141
1142 item = list_head(&out->offload_cmd_list);
1143 cmd = node_to_item(item, struct offload_cmd, node);
1144 list_remove(item);
1145
1146 ALOGVV("%s STATE %d CMD %d out->compr %p",
1147 __func__, out->offload_state, cmd->cmd, out->compr);
1148
1149 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1150 free(cmd);
1151 break;
1152 }
1153
1154 if (out->compr == NULL) {
1155 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001156 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001157 pthread_cond_signal(&out->cond);
1158 continue;
1159 }
1160 out->offload_thread_blocked = true;
1161 pthread_mutex_unlock(&out->lock);
1162 send_callback = false;
1163 switch(cmd->cmd) {
1164 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1165 compress_wait(out->compr, -1);
1166 send_callback = true;
1167 event = STREAM_CBK_EVENT_WRITE_READY;
1168 break;
1169 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001170 compress_next_track(out->compr);
1171 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001172 send_callback = true;
1173 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001174 /* Resend the metadata for next iteration */
1175 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001176 break;
1177 case OFFLOAD_CMD_DRAIN:
1178 compress_drain(out->compr);
1179 send_callback = true;
1180 event = STREAM_CBK_EVENT_DRAIN_READY;
1181 break;
1182 default:
1183 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1184 break;
1185 }
Eric Laurenta1478072015-09-21 17:21:52 -07001186 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001187 out->offload_thread_blocked = false;
1188 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001189 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001190 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001191 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001192 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001193 free(cmd);
1194 }
1195
1196 pthread_cond_signal(&out->cond);
1197 while (!list_empty(&out->offload_cmd_list)) {
1198 item = list_head(&out->offload_cmd_list);
1199 list_remove(item);
1200 free(node_to_item(item, struct offload_cmd, node));
1201 }
1202 pthread_mutex_unlock(&out->lock);
1203
1204 return NULL;
1205}
1206
1207static int create_offload_callback_thread(struct stream_out *out)
1208{
1209 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1210 list_init(&out->offload_cmd_list);
1211 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1212 offload_thread_loop, out);
1213 return 0;
1214}
1215
1216static int destroy_offload_callback_thread(struct stream_out *out)
1217{
Eric Laurenta1478072015-09-21 17:21:52 -07001218 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001219 stop_compressed_output_l(out);
1220 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1221
1222 pthread_mutex_unlock(&out->lock);
1223 pthread_join(out->offload_thread, (void **) NULL);
1224 pthread_cond_destroy(&out->offload_cond);
1225
1226 return 0;
1227}
1228
Eric Laurent07eeafd2013-10-06 12:52:49 -07001229static bool allow_hdmi_channel_config(struct audio_device *adev)
1230{
1231 struct listnode *node;
1232 struct audio_usecase *usecase;
1233 bool ret = true;
1234
1235 list_for_each(node, &adev->usecase_list) {
1236 usecase = node_to_item(node, struct audio_usecase, list);
1237 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1238 /*
1239 * If voice call is already existing, do not proceed further to avoid
1240 * disabling/enabling both RX and TX devices, CSD calls, etc.
1241 * Once the voice call done, the HDMI channels can be configured to
1242 * max channels of remaining use cases.
1243 */
1244 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001245 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001246 __func__);
1247 ret = false;
1248 break;
1249 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001250 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001251 "no change in HDMI channels", __func__);
1252 ret = false;
1253 break;
1254 }
1255 }
1256 }
1257 return ret;
1258}
1259
1260static int check_and_set_hdmi_channels(struct audio_device *adev,
1261 unsigned int channels)
1262{
1263 struct listnode *node;
1264 struct audio_usecase *usecase;
1265
1266 /* Check if change in HDMI channel config is allowed */
1267 if (!allow_hdmi_channel_config(adev))
1268 return 0;
1269
1270 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001271 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001272 return 0;
1273 }
1274
1275 platform_set_hdmi_channels(adev->platform, channels);
1276 adev->cur_hdmi_channels = channels;
1277
1278 /*
1279 * Deroute all the playback streams routed to HDMI so that
1280 * the back end is deactivated. Note that backend will not
1281 * be deactivated if any one stream is connected to it.
1282 */
1283 list_for_each(node, &adev->usecase_list) {
1284 usecase = node_to_item(node, struct audio_usecase, list);
1285 if (usecase->type == PCM_PLAYBACK &&
1286 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001287 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001288 }
1289 }
1290
1291 /*
1292 * Enable all the streams disabled above. Now the HDMI backend
1293 * will be activated with new channel configuration
1294 */
1295 list_for_each(node, &adev->usecase_list) {
1296 usecase = node_to_item(node, struct audio_usecase, list);
1297 if (usecase->type == PCM_PLAYBACK &&
1298 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001299 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001300 }
1301 }
1302
1303 return 0;
1304}
1305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001306static int stop_output_stream(struct stream_out *out)
1307{
1308 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001309 struct audio_usecase *uc_info;
1310 struct audio_device *adev = out->dev;
1311
Eric Laurent994a6932013-07-17 11:51:42 -07001312 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001313 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314 uc_info = get_usecase_from_list(adev, out->usecase);
1315 if (uc_info == NULL) {
1316 ALOGE("%s: Could not find the usecase (%d) in the list",
1317 __func__, out->usecase);
1318 return -EINVAL;
1319 }
1320
Haynes Mathew George41f86652014-06-17 14:22:15 -07001321 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1322 if (adev->visualizer_stop_output != NULL)
1323 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1324 if (adev->offload_effects_stop_output != NULL)
1325 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1326 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001327
Eric Laurent150dbfe2013-02-27 14:31:02 -08001328 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001329 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001330
1331 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001332 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001333
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001334 list_remove(&uc_info->list);
1335 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001336
Eric Laurent0499d4f2014-08-25 22:39:29 -05001337 audio_extn_extspk_update(adev->extspk);
1338
Eric Laurent07eeafd2013-10-06 12:52:49 -07001339 /* Must be called after removing the usecase from list */
1340 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1341 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1342
Eric Laurent994a6932013-07-17 11:51:42 -07001343 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 return ret;
1345}
1346
1347int start_output_stream(struct stream_out *out)
1348{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001349 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350 struct audio_usecase *uc_info;
1351 struct audio_device *adev = out->dev;
1352
Eric Laurent994a6932013-07-17 11:51:42 -07001353 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001354 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001355 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001356 if (out->pcm_device_id < 0) {
1357 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1358 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001359 ret = -EINVAL;
1360 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001361 }
1362
1363 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1364 uc_info->id = out->usecase;
1365 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001366 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001367 uc_info->devices = out->devices;
1368 uc_info->in_snd_device = SND_DEVICE_NONE;
1369 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001370
Eric Laurent07eeafd2013-10-06 12:52:49 -07001371 /* This must be called before adding this usecase to the list */
1372 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1373 check_and_set_hdmi_channels(adev, out->config.channels);
1374
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001375 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001376
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001377 audio_extn_perf_lock_acquire();
1378
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001379 select_devices(adev, out->usecase);
1380
Eric Laurent0499d4f2014-08-25 22:39:29 -05001381 audio_extn_extspk_update(adev->extspk);
1382
Andy Hung31aca912014-03-20 17:14:59 -07001383 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001384 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001385 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001386 unsigned int flags = PCM_OUT;
1387 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001388
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001389 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1390 flags |= PCM_MMAP | PCM_NOIRQ;
1391 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001392 } else if (out->realtime) {
1393 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001394 } else
1395 flags |= PCM_MONOTONIC;
1396
1397 while (1) {
1398 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1399 flags, &out->config);
1400 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1401 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1402 if (out->pcm != NULL) {
1403 pcm_close(out->pcm);
1404 out->pcm = NULL;
1405 }
1406 if (pcm_open_retry_count-- == 0) {
1407 ret = -EIO;
1408 goto error_open;
1409 }
1410 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1411 continue;
1412 }
1413 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001414 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001415 ALOGV("%s: pcm_prepare", __func__);
1416 if (pcm_is_ready(out->pcm)) {
1417 ret = pcm_prepare(out->pcm);
1418 if (ret < 0) {
1419 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1420 pcm_close(out->pcm);
1421 out->pcm = NULL;
1422 goto error_open;
1423 }
1424 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001425 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001426 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001427 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001428 COMPRESS_IN, &out->compr_config);
1429 if (out->compr && !is_compress_ready(out->compr)) {
1430 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1431 compress_close(out->compr);
1432 out->compr = NULL;
1433 ret = -EIO;
1434 goto error_open;
1435 }
1436 if (out->offload_callback)
1437 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001438
1439 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001440 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1441 if (adev->offload_effects_start_output != NULL)
1442 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001443 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001444 ret = 0;
1445 register_out_stream(out);
1446 if (out->realtime) {
1447 ret = pcm_start(out->pcm);
1448 }
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001449 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001450 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001451 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001452error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001453 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001454 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001455error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001456 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457}
1458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459static int check_input_parameters(uint32_t sample_rate,
1460 audio_format_t format,
1461 int channel_count)
1462{
vivek mehta4ed66e62016-04-15 23:33:34 -07001463 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001464 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1465 return -EINVAL;
1466 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001467
vivek mehtadae44712015-07-27 14:13:18 -07001468 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001469 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001470 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1471 return -EINVAL;
1472 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001473
1474 switch (sample_rate) {
1475 case 8000:
1476 case 11025:
1477 case 12000:
1478 case 16000:
1479 case 22050:
1480 case 24000:
1481 case 32000:
1482 case 44100:
1483 case 48000:
1484 break;
1485 default:
vivek mehtadae44712015-07-27 14:13:18 -07001486 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487 return -EINVAL;
1488 }
1489
1490 return 0;
1491}
1492
1493static size_t get_input_buffer_size(uint32_t sample_rate,
1494 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001495 int channel_count,
1496 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497{
1498 size_t size = 0;
1499
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001500 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1501 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001502
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001503 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001504 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001505 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001506
1507 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001508
Glenn Kasten4f993392014-05-14 07:30:48 -07001509 /* make sure the size is multiple of 32 bytes
1510 * At 48 kHz mono 16-bit PCM:
1511 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1512 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1513 */
1514 size += 0x1f;
1515 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001516
1517 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518}
1519
1520static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1521{
1522 struct stream_out *out = (struct stream_out *)stream;
1523
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001524 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525}
1526
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001527static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528{
1529 return -ENOSYS;
1530}
1531
1532static size_t out_get_buffer_size(const struct audio_stream *stream)
1533{
1534 struct stream_out *out = (struct stream_out *)stream;
1535
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001536 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1537 return out->compr_config.fragment_size;
1538 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001539 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001540 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001541}
1542
1543static uint32_t out_get_channels(const struct audio_stream *stream)
1544{
1545 struct stream_out *out = (struct stream_out *)stream;
1546
1547 return out->channel_mask;
1548}
1549
1550static audio_format_t out_get_format(const struct audio_stream *stream)
1551{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001552 struct stream_out *out = (struct stream_out *)stream;
1553
1554 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555}
1556
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001557static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001558{
1559 return -ENOSYS;
1560}
1561
1562static int out_standby(struct audio_stream *stream)
1563{
1564 struct stream_out *out = (struct stream_out *)stream;
1565 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001566
Eric Laurent994a6932013-07-17 11:51:42 -07001567 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001568 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001569
Eric Laurenta1478072015-09-21 17:21:52 -07001570 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001571 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001572 if (adev->adm_deregister_stream)
1573 adev->adm_deregister_stream(adev->adm_data, out->handle);
1574
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001575 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001576 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001577 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1578 if (out->pcm) {
1579 pcm_close(out->pcm);
1580 out->pcm = NULL;
1581 }
1582 } else {
1583 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001584 out->gapless_mdata.encoder_delay = 0;
1585 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001586 if (out->compr != NULL) {
1587 compress_close(out->compr);
1588 out->compr = NULL;
1589 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001592 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593 }
1594 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001595 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596 return 0;
1597}
1598
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001599static int out_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001600{
1601 return 0;
1602}
1603
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001604static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1605{
1606 int ret = 0;
1607 char value[32];
1608 struct compr_gapless_mdata tmp_mdata;
1609
1610 if (!out || !parms) {
1611 return -EINVAL;
1612 }
1613
1614 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1615 if (ret >= 0) {
1616 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1617 } else {
1618 return -EINVAL;
1619 }
1620
1621 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1622 if (ret >= 0) {
1623 tmp_mdata.encoder_padding = atoi(value);
1624 } else {
1625 return -EINVAL;
1626 }
1627
1628 out->gapless_mdata = tmp_mdata;
1629 out->send_new_metadata = 1;
1630 ALOGV("%s new encoder delay %u and padding %u", __func__,
1631 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1632
1633 return 0;
1634}
1635
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001636static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1637{
1638 return out == adev->primary_output || out == adev->voice_tx_output;
1639}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001640
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001641static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1642{
1643 struct stream_out *out = (struct stream_out *)stream;
1644 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001645 struct audio_usecase *usecase;
1646 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001647 struct str_parms *parms;
1648 char value[32];
1649 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001650 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001651 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652
Joe Onorato188b6222016-03-01 11:02:27 -08001653 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001654 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655 parms = str_parms_create_str(kvpairs);
1656 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1657 if (ret >= 0) {
1658 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001659 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001660 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001662 /*
1663 * When HDMI cable is unplugged the music playback is paused and
1664 * the policy manager sends routing=0. But the audioflinger
1665 * continues to write data until standby time (3sec).
1666 * As the HDMI core is turned off, the write gets blocked.
1667 * Avoid this by routing audio to speaker until standby.
1668 */
1669 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1670 val == AUDIO_DEVICE_NONE) {
1671 val = AUDIO_DEVICE_OUT_SPEAKER;
1672 }
1673
1674 /*
1675 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001676 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001677 * the select_devices(). But how do we undo this?
1678 *
1679 * For example, music playback is active on headset (deep-buffer usecase)
1680 * and if we go to ringtones and select a ringtone, low-latency usecase
1681 * will be started on headset+speaker. As we can't enable headset+speaker
1682 * and headset devices at the same time, select_devices() switches the music
1683 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1684 * So when the ringtone playback is completed, how do we undo the same?
1685 *
1686 * We are relying on the out_set_parameters() call on deep-buffer output,
1687 * once the ringtone playback is ended.
1688 * NOTE: We should not check if the current devices are same as new devices.
1689 * Because select_devices() must be called to switch back the music
1690 * playback to headset.
1691 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08001692 audio_devices_t new_dev = val;
1693 if (new_dev != AUDIO_DEVICE_NONE) {
1694 bool same_dev = out->devices == new_dev;
1695 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001696
Haynes Mathew George03c40102016-01-29 17:57:48 -08001697 if (!out->standby) {
1698 if (!same_dev) {
1699 ALOGV("update routing change");
1700 out->routing_change = true;
1701 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001702 select_devices(adev, out->usecase);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001703 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001704
Eric Laurenta7657192014-10-09 21:09:33 -07001705 if (output_drives_call(adev, out)) {
1706 if (!voice_is_in_call(adev)) {
1707 if (adev->mode == AUDIO_MODE_IN_CALL) {
1708 adev->current_call_output = out;
1709 ret = voice_start_call(adev);
1710 }
1711 } else {
1712 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001713 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07001714 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001715 }
1716 }
1717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001718 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001719 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05001720
1721 /*handles device and call state changes*/
1722 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001724
1725 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1726 parse_compress_metadata(out, parms);
1727 }
1728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07001730 ALOGV("%s: exit: code(%d)", __func__, status);
1731 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732}
1733
1734static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1735{
1736 struct stream_out *out = (struct stream_out *)stream;
1737 struct str_parms *query = str_parms_create_str(keys);
1738 char *str;
1739 char value[256];
1740 struct str_parms *reply = str_parms_create();
1741 size_t i, j;
1742 int ret;
1743 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07001744 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1746 if (ret >= 0) {
1747 value[0] = '\0';
1748 i = 0;
1749 while (out->supported_channel_masks[i] != 0) {
1750 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1751 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1752 if (!first) {
1753 strcat(value, "|");
1754 }
1755 strcat(value, out_channels_name_to_enum_table[j].name);
1756 first = false;
1757 break;
1758 }
1759 }
1760 i++;
1761 }
1762 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1763 str = str_parms_to_str(reply);
1764 } else {
1765 str = strdup(keys);
1766 }
1767 str_parms_destroy(query);
1768 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001769 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770 return str;
1771}
1772
1773static uint32_t out_get_latency(const struct audio_stream_out *stream)
1774{
Haynes Mathew George03c40102016-01-29 17:57:48 -08001775 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001776 struct stream_out *out = (struct stream_out *)stream;
1777
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001778 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
1779 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001780 else if (out->realtime) {
1781 // since the buffer won't be filled up faster than realtime,
1782 // return a smaller number
1783 period_ms = (out->af_period_multiplier * out->config.period_size *
1784 1000) / (out->config.rate);
1785 hw_delay = platform_render_latency(out->usecase)/1000;
1786 return period_ms + hw_delay;
1787 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001788
1789 return (out->config.period_count * out->config.period_size * 1000) /
1790 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791}
1792
1793static int out_set_volume(struct audio_stream_out *stream, float left,
1794 float right)
1795{
Eric Laurenta9024de2013-04-04 09:19:12 -07001796 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001797 int volume[2];
1798
Eric Laurenta9024de2013-04-04 09:19:12 -07001799 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1800 /* only take left channel into account: the API is for stereo anyway */
1801 out->muted = (left == 0.0f);
1802 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001803 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1804 const char *mixer_ctl_name = "Compress Playback Volume";
1805 struct audio_device *adev = out->dev;
1806 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1808 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07001809 /* try with the control based on device id */
1810 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
1811 PCM_PLAYBACK);
1812 char ctl_name[128] = {0};
1813 snprintf(ctl_name, sizeof(ctl_name),
1814 "Compress Playback %d Volume", pcm_device_id);
1815 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
1816 if (!ctl) {
1817 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
1818 return -EINVAL;
1819 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001820 }
1821 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
1822 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
1823 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
1824 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07001825 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827 return -ENOSYS;
1828}
1829
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001830#ifdef NO_AUDIO_OUT
1831static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
1832 const void *buffer, size_t bytes)
1833{
1834 struct stream_out *out = (struct stream_out *)stream;
1835
1836 /* No Output device supported other than BT for playback.
1837 * Sleep for the amount of buffer duration
1838 */
Eric Laurenta1478072015-09-21 17:21:52 -07001839 lock_output_stream(out);
Uday Kishore Pasupuletib14d76b2015-11-13 20:06:37 -08001840 usleep(bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001841 out_get_sample_rate(&out->stream.common));
1842 pthread_mutex_unlock(&out->lock);
1843 return bytes;
1844}
1845#endif
1846
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001847static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1848 size_t bytes)
1849{
1850 struct stream_out *out = (struct stream_out *)stream;
1851 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07001852 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853
Eric Laurenta1478072015-09-21 17:21:52 -07001854 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001856 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001857 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001859 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001860 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001862 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 goto exit;
1864 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001866
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001867 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001868 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
1869 if (out->send_new_metadata) {
1870 ALOGVV("send new gapless metadata");
1871 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
1872 out->send_new_metadata = 0;
1873 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08001874 unsigned int avail;
1875 struct timespec tstamp;
1876 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
1877 /* Do not limit write size if the available frames count is unknown */
1878 if (ret != 0) {
1879 avail = bytes;
1880 }
1881 if (avail == 0) {
1882 ret = 0;
1883 } else {
1884 if (avail > bytes) {
1885 avail = bytes;
1886 }
1887 ret = compress_write(out->compr, buffer, avail);
1888 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
1889 __func__, avail, ret);
1890 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001891
Eric Laurent6e895242013-09-05 16:10:57 -07001892 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001893 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
1894 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08001895 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001896 compress_start(out->compr);
1897 out->playback_started = 1;
1898 out->offload_state = OFFLOAD_STATE_PLAYING;
1899 }
1900 pthread_mutex_unlock(&out->lock);
1901 return ret;
1902 } else {
1903 if (out->pcm) {
1904 if (out->muted)
1905 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001906
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001907 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001908
Haynes Mathew George03c40102016-01-29 17:57:48 -08001909 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
1910 out->config.rate;
1911 request_out_focus(out, ns);
1912
1913 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
1914 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001915 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001916 else
1917 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001918
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001919 if (ret == 0)
1920 out->written += bytes / (out->config.channels * sizeof(short));
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001921
Haynes Mathew George03c40102016-01-29 17:57:48 -08001922 release_out_focus(out, ns);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001923 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924 }
1925
1926exit:
1927 pthread_mutex_unlock(&out->lock);
1928
1929 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001930 if (out->pcm)
vivek mehta1a9b7c02015-06-25 11:49:38 -07001931 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932 out_standby(&out->stream.common);
Eric Laurentfdf296a2014-07-03 16:41:51 -07001933 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934 out_get_sample_rate(&out->stream.common));
1935 }
1936 return bytes;
1937}
1938
1939static int out_get_render_position(const struct audio_stream_out *stream,
1940 uint32_t *dsp_frames)
1941{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001942 struct stream_out *out = (struct stream_out *)stream;
1943 *dsp_frames = 0;
1944 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07001945 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001946 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08001947 unsigned long frames = 0;
1948 // TODO: check return value
1949 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
1950 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001951 ALOGVV("%s rendered frames %d sample_rate %d",
1952 __func__, *dsp_frames, out->sample_rate);
1953 }
1954 pthread_mutex_unlock(&out->lock);
1955 return 0;
1956 } else
1957 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001958}
1959
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001960static int out_add_audio_effect(const struct audio_stream *stream __unused,
1961 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962{
1963 return 0;
1964}
1965
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001966static int out_remove_audio_effect(const struct audio_stream *stream __unused,
1967 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968{
1969 return 0;
1970}
1971
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001972static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
1973 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974{
1975 return -EINVAL;
1976}
1977
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001978static int out_get_presentation_position(const struct audio_stream_out *stream,
1979 uint64_t *frames, struct timespec *timestamp)
1980{
1981 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08001982 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07001983 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001984
Eric Laurenta1478072015-09-21 17:21:52 -07001985 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001986
Eric Laurent949a0892013-09-20 09:20:13 -07001987 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1988 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08001989 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07001990 compress_get_tstamp(out->compr, &dsp_frames,
1991 &out->sample_rate);
1992 ALOGVV("%s rendered frames %ld sample_rate %d",
1993 __func__, dsp_frames, out->sample_rate);
1994 *frames = dsp_frames;
1995 ret = 0;
1996 /* this is the best we can do */
1997 clock_gettime(CLOCK_MONOTONIC, timestamp);
1998 }
1999 } else {
2000 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07002001 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002002 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2003 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002004 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002005 // This adjustment accounts for buffering after app processor.
2006 // It is based on estimated DSP latency per use case, rather than exact.
2007 signed_frames -=
2008 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2009
Eric Laurent949a0892013-09-20 09:20:13 -07002010 // It would be unusual for this value to be negative, but check just in case ...
2011 if (signed_frames >= 0) {
2012 *frames = signed_frames;
2013 ret = 0;
2014 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002015 }
2016 }
2017 }
2018
2019 pthread_mutex_unlock(&out->lock);
2020
2021 return ret;
2022}
2023
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002024static int out_set_callback(struct audio_stream_out *stream,
2025 stream_callback_t callback, void *cookie)
2026{
2027 struct stream_out *out = (struct stream_out *)stream;
2028
2029 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002030 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002031 out->offload_callback = callback;
2032 out->offload_cookie = cookie;
2033 pthread_mutex_unlock(&out->lock);
2034 return 0;
2035}
2036
2037static int out_pause(struct audio_stream_out* stream)
2038{
2039 struct stream_out *out = (struct stream_out *)stream;
2040 int status = -ENOSYS;
2041 ALOGV("%s", __func__);
2042 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002043 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002044 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2045 status = compress_pause(out->compr);
2046 out->offload_state = OFFLOAD_STATE_PAUSED;
2047 }
2048 pthread_mutex_unlock(&out->lock);
2049 }
2050 return status;
2051}
2052
2053static int out_resume(struct audio_stream_out* stream)
2054{
2055 struct stream_out *out = (struct stream_out *)stream;
2056 int status = -ENOSYS;
2057 ALOGV("%s", __func__);
2058 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2059 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002060 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002061 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2062 status = compress_resume(out->compr);
2063 out->offload_state = OFFLOAD_STATE_PLAYING;
2064 }
2065 pthread_mutex_unlock(&out->lock);
2066 }
2067 return status;
2068}
2069
2070static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2071{
2072 struct stream_out *out = (struct stream_out *)stream;
2073 int status = -ENOSYS;
2074 ALOGV("%s", __func__);
2075 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002076 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002077 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2078 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2079 else
2080 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2081 pthread_mutex_unlock(&out->lock);
2082 }
2083 return status;
2084}
2085
2086static int out_flush(struct audio_stream_out* stream)
2087{
2088 struct stream_out *out = (struct stream_out *)stream;
2089 ALOGV("%s", __func__);
2090 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002091 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002092 stop_compressed_output_l(out);
2093 pthread_mutex_unlock(&out->lock);
2094 return 0;
2095 }
2096 return -ENOSYS;
2097}
2098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002099/** audio_stream_in implementation **/
2100static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2101{
2102 struct stream_in *in = (struct stream_in *)stream;
2103
2104 return in->config.rate;
2105}
2106
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002107static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108{
2109 return -ENOSYS;
2110}
2111
2112static size_t in_get_buffer_size(const struct audio_stream *stream)
2113{
2114 struct stream_in *in = (struct stream_in *)stream;
2115
Haynes Mathew George03c40102016-01-29 17:57:48 -08002116 return in->config.period_size * in->af_period_multiplier *
2117 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118}
2119
2120static uint32_t in_get_channels(const struct audio_stream *stream)
2121{
2122 struct stream_in *in = (struct stream_in *)stream;
2123
2124 return in->channel_mask;
2125}
2126
vivek mehta4ed66e62016-04-15 23:33:34 -07002127static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128{
vivek mehta4ed66e62016-04-15 23:33:34 -07002129 struct stream_in *in = (struct stream_in *)stream;
2130 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131}
2132
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002133static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002134{
2135 return -ENOSYS;
2136}
2137
2138static int in_standby(struct audio_stream *stream)
2139{
2140 struct stream_in *in = (struct stream_in *)stream;
2141 struct audio_device *adev = in->dev;
2142 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002143 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002144
2145 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002146
2147 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002148 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002149 audio_extn_sound_trigger_stop_lab(in);
2150 in->standby = true;
2151 }
2152
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002154 if (adev->adm_deregister_stream)
2155 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2156
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002157 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002159 if (in->pcm) {
2160 pcm_close(in->pcm);
2161 in->pcm = NULL;
2162 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002163 adev->enable_voicerx = false;
2164 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002166 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002167 }
2168 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002169 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170 return status;
2171}
2172
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002173static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002174{
2175 return 0;
2176}
2177
2178static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2179{
2180 struct stream_in *in = (struct stream_in *)stream;
2181 struct audio_device *adev = in->dev;
2182 struct str_parms *parms;
2183 char *str;
2184 char value[32];
2185 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002186 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187
Eric Laurent994a6932013-07-17 11:51:42 -07002188 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002189 parms = str_parms_create_str(kvpairs);
2190
2191 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2192
Eric Laurenta1478072015-09-21 17:21:52 -07002193 lock_input_stream(in);
2194
Eric Laurent150dbfe2013-02-27 14:31:02 -08002195 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002196 if (ret >= 0) {
2197 val = atoi(value);
2198 /* no audio source uses val == 0 */
2199 if ((in->source != val) && (val != 0)) {
2200 in->source = val;
2201 }
2202 }
2203
2204 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002205
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002206 if (ret >= 0) {
2207 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002208 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 in->device = val;
2210 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002211 if (!in->standby) {
2212 ALOGV("update input routing change");
2213 in->routing_change = true;
2214 select_devices(adev, in->usecase);
2215 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002216 }
2217 }
2218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002220 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221
2222 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002223 ALOGV("%s: exit: status(%d)", __func__, status);
2224 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225}
2226
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002227static char* in_get_parameters(const struct audio_stream *stream __unused,
2228 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229{
2230 return strdup("");
2231}
2232
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002233static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234{
2235 return 0;
2236}
2237
2238static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2239 size_t bytes)
2240{
2241 struct stream_in *in = (struct stream_in *)stream;
2242 struct audio_device *adev = in->dev;
2243 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002244 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002245
Eric Laurenta1478072015-09-21 17:21:52 -07002246 lock_input_stream(in);
2247
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002248 if (in->is_st_session) {
2249 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2250 /* Read from sound trigger HAL */
2251 audio_extn_sound_trigger_read(in, buffer, bytes);
2252 pthread_mutex_unlock(&in->lock);
2253 return bytes;
2254 }
2255
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002257 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002259 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261 goto exit;
2262 }
2263 in->standby = 0;
2264 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265
Haynes Mathew George03c40102016-01-29 17:57:48 -08002266 //what's the duration requested by the client?
2267 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2268 in->config.rate;
2269 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002270
Haynes Mathew George03c40102016-01-29 17:57:48 -08002271 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002273 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002274 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002275 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002276 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002277 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002278 if (ret < 0) {
2279 ALOGE("Failed to read w/err %s", strerror(errno));
2280 ret = -errno;
2281 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002282 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2283 if (bytes % 4 == 0) {
2284 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2285 int_buf_stream = buffer;
2286 for (size_t itt=0; itt < bytes/4 ; itt++) {
2287 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002288 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002289 } else {
2290 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2291 ret = -EINVAL;
2292 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002293 }
2294 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002295 }
2296
Haynes Mathew George03c40102016-01-29 17:57:48 -08002297 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002299 /*
2300 * Instead of writing zeroes here, we could trust the hardware
2301 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002302 * 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 -08002303 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002304 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002305 memset(buffer, 0, bytes);
2306
2307exit:
2308 pthread_mutex_unlock(&in->lock);
2309
2310 if (ret != 0) {
2311 in_standby(&in->stream.common);
2312 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002313 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002314 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002315 memset(buffer, 0, bytes); // clear return data
2316 }
2317 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002318 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002319 }
2320 return bytes;
2321}
2322
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002323static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002324{
2325 return 0;
2326}
2327
Andy Hung6ebe5962016-01-15 17:46:57 -08002328static int in_get_capture_position(const struct audio_stream_in *stream,
2329 int64_t *frames, int64_t *time)
2330{
2331 if (stream == NULL || frames == NULL || time == NULL) {
2332 return -EINVAL;
2333 }
2334 struct stream_in *in = (struct stream_in *)stream;
2335 int ret = -ENOSYS;
2336
2337 lock_input_stream(in);
2338 if (in->pcm) {
2339 struct timespec timestamp;
2340 unsigned int avail;
2341 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2342 *frames = in->frames_read + avail;
2343 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2344 ret = 0;
2345 }
2346 }
2347 pthread_mutex_unlock(&in->lock);
2348 return ret;
2349}
2350
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002351static int add_remove_audio_effect(const struct audio_stream *stream,
2352 effect_handle_t effect,
2353 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002354{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002355 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002356 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002357 int status = 0;
2358 effect_descriptor_t desc;
2359
2360 status = (*effect)->get_descriptor(effect, &desc);
2361 if (status != 0)
2362 return status;
2363
Eric Laurenta1478072015-09-21 17:21:52 -07002364 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002365 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002366 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002367 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002368 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002369 in->enable_aec != enable &&
2370 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2371 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002372 if (!enable)
2373 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002374 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2375 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2376 adev->enable_voicerx = enable;
2377 struct audio_usecase *usecase;
2378 struct listnode *node;
2379 list_for_each(node, &adev->usecase_list) {
2380 usecase = node_to_item(node, struct audio_usecase, list);
2381 if (usecase->type == PCM_PLAYBACK) {
2382 select_devices(adev, usecase->id);
2383 break;
2384 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002385 }
2386 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002387 if (!in->standby)
2388 select_devices(in->dev, in->usecase);
2389 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002390 if (in->enable_ns != enable &&
2391 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2392 in->enable_ns = enable;
2393 if (!in->standby)
2394 select_devices(in->dev, in->usecase);
2395 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002396 pthread_mutex_unlock(&in->dev->lock);
2397 pthread_mutex_unlock(&in->lock);
2398
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002399 return 0;
2400}
2401
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002402static int in_add_audio_effect(const struct audio_stream *stream,
2403 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404{
Eric Laurent994a6932013-07-17 11:51:42 -07002405 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002406 return add_remove_audio_effect(stream, effect, true);
2407}
2408
2409static int in_remove_audio_effect(const struct audio_stream *stream,
2410 effect_handle_t effect)
2411{
Eric Laurent994a6932013-07-17 11:51:42 -07002412 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002413 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414}
2415
2416static int adev_open_output_stream(struct audio_hw_device *dev,
2417 audio_io_handle_t handle,
2418 audio_devices_t devices,
2419 audio_output_flags_t flags,
2420 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002421 struct audio_stream_out **stream_out,
2422 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002423{
2424 struct audio_device *adev = (struct audio_device *)dev;
2425 struct stream_out *out;
2426 int i, ret;
2427
Eric Laurent994a6932013-07-17 11:51:42 -07002428 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429 __func__, config->sample_rate, config->channel_mask, devices, flags);
2430 *stream_out = NULL;
2431 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2432
2433 if (devices == AUDIO_DEVICE_NONE)
2434 devices = AUDIO_DEVICE_OUT_SPEAKER;
2435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002436 out->flags = flags;
2437 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002438 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002439 out->format = config->format;
2440 out->sample_rate = config->sample_rate;
2441 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2442 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002443 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002444
2445 /* Init use case and pcm_config */
2446 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002447 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002449 pthread_mutex_lock(&adev->lock);
2450 ret = read_hdmi_channel_masks(out);
2451 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002452 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002453 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002454
2455 if (config->sample_rate == 0)
2456 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2457 if (config->channel_mask == 0)
2458 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002459 if (config->format == AUDIO_FORMAT_DEFAULT)
2460 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002461
2462 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002463 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002464 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2466 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002468 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002469 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002470 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2471 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2472 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2473 ALOGE("%s: Unsupported Offload information", __func__);
2474 ret = -EINVAL;
2475 goto error_open;
2476 }
2477 if (!is_supported_format(config->offload_info.format)) {
2478 ALOGE("%s: Unsupported audio format", __func__);
2479 ret = -EINVAL;
2480 goto error_open;
2481 }
2482
2483 out->compr_config.codec = (struct snd_codec *)
2484 calloc(1, sizeof(struct snd_codec));
2485
2486 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2487 if (config->offload_info.channel_mask)
2488 out->channel_mask = config->offload_info.channel_mask;
2489 else if (config->channel_mask)
2490 out->channel_mask = config->channel_mask;
2491 out->format = config->offload_info.format;
2492 out->sample_rate = config->offload_info.sample_rate;
2493
2494 out->stream.set_callback = out_set_callback;
2495 out->stream.pause = out_pause;
2496 out->stream.resume = out_resume;
2497 out->stream.drain = out_drain;
2498 out->stream.flush = out_flush;
2499
2500 out->compr_config.codec->id =
2501 get_snd_codec_id(config->offload_info.format);
2502 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2503 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002504 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002505 out->compr_config.codec->bit_rate =
2506 config->offload_info.bit_rate;
2507 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002508 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002509 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2510
2511 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2512 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002513
2514 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002515 create_offload_callback_thread(out);
2516 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2517 __func__, config->offload_info.version,
2518 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002519 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2520 if (config->sample_rate == 0)
2521 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2522 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2523 config->sample_rate != 8000) {
2524 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2525 ret = -EINVAL;
2526 goto error_open;
2527 }
2528 out->sample_rate = config->sample_rate;
2529 out->config.rate = config->sample_rate;
2530 if (config->format == AUDIO_FORMAT_DEFAULT)
2531 config->format = AUDIO_FORMAT_PCM_16_BIT;
2532 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2533 config->format = AUDIO_FORMAT_PCM_16_BIT;
2534 ret = -EINVAL;
2535 goto error_open;
2536 }
2537 out->format = config->format;
2538 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2539 out->config = pcm_config_afe_proxy_playback;
2540 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002541 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002542 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2543 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2544 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002545 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2546 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2547 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002548 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2549 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002550 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2551 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2552 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002553 } else {
2554 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2555 out->config = pcm_config_low_latency;
2556 }
2557 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2558 if (k_enable_extended_precision
2559 && pcm_params_format_test(adev->use_case_table[out->usecase],
2560 pcm_format_from_audio_format(config->format))) {
2561 out->config.format = pcm_format_from_audio_format(config->format);
2562 /* out->format already set to config->format */
2563 } else {
2564 /* deny the externally proposed config format
2565 * and use the one specified in audio_hw layer configuration.
2566 * Note: out->format is returned by out->stream.common.get_format()
2567 * and is used to set config->format in the code several lines below.
2568 */
2569 out->format = audio_format_from_pcm_format(out->config.format);
2570 }
2571 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002572 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07002574 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
2575 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002577 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002578 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002579 adev->primary_output = out;
2580 else {
2581 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002582 ret = -EEXIST;
2583 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002584 }
2585 }
2586
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002587 /* Check if this usecase is already existing */
2588 pthread_mutex_lock(&adev->lock);
2589 if (get_usecase_from_list(adev, out->usecase) != NULL) {
2590 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002591 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002592 ret = -EEXIST;
2593 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002594 }
2595 pthread_mutex_unlock(&adev->lock);
2596
2597 out->stream.common.get_sample_rate = out_get_sample_rate;
2598 out->stream.common.set_sample_rate = out_set_sample_rate;
2599 out->stream.common.get_buffer_size = out_get_buffer_size;
2600 out->stream.common.get_channels = out_get_channels;
2601 out->stream.common.get_format = out_get_format;
2602 out->stream.common.set_format = out_set_format;
2603 out->stream.common.standby = out_standby;
2604 out->stream.common.dump = out_dump;
2605 out->stream.common.set_parameters = out_set_parameters;
2606 out->stream.common.get_parameters = out_get_parameters;
2607 out->stream.common.add_audio_effect = out_add_audio_effect;
2608 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2609 out->stream.get_latency = out_get_latency;
2610 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002611#ifdef NO_AUDIO_OUT
2612 out->stream.write = out_write_for_no_output;
2613#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002615#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 out->stream.get_render_position = out_get_render_position;
2617 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002618 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619
Haynes Mathew George03c40102016-01-29 17:57:48 -08002620 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002622 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002623 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002625 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07002626 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002627 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2628
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 config->format = out->stream.common.get_format(&out->stream.common);
2630 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2631 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2632
2633 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002634 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002636
2637error_open:
2638 free(out);
2639 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07002640 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002641 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002642}
2643
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002644static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 struct audio_stream_out *stream)
2646{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002647 struct stream_out *out = (struct stream_out *)stream;
2648 struct audio_device *adev = out->dev;
2649
Eric Laurent994a6932013-07-17 11:51:42 -07002650 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002651 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002652 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2653 destroy_offload_callback_thread(out);
2654
2655 if (out->compr_config.codec != NULL)
2656 free(out->compr_config.codec);
2657 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07002658
2659 if (adev->voice_tx_output == out)
2660 adev->voice_tx_output = NULL;
2661
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002662 pthread_cond_destroy(&out->cond);
2663 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002665 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666}
2667
2668static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2669{
2670 struct audio_device *adev = (struct audio_device *)dev;
2671 struct str_parms *parms;
2672 char *str;
2673 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002674 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07002676 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677
Joe Onorato188b6222016-03-01 11:02:27 -08002678 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002679
2680 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681
2682 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002683 status = voice_set_parameters(adev, parms);
2684 if (status != 0) {
2685 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002686 }
2687
2688 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
2689 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07002690 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002691 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2692 adev->bluetooth_nrec = true;
2693 else
2694 adev->bluetooth_nrec = false;
2695 }
2696
2697 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
2698 if (ret >= 0) {
2699 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2700 adev->screen_off = false;
2701 else
2702 adev->screen_off = true;
2703 }
2704
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002705 ret = str_parms_get_int(parms, "rotation", &val);
2706 if (ret >= 0) {
2707 bool reverse_speakers = false;
2708 switch(val) {
2709 // FIXME: note that the code below assumes that the speakers are in the correct placement
2710 // relative to the user when the device is rotated 90deg from its default rotation. This
2711 // assumption is device-specific, not platform-specific like this code.
2712 case 270:
2713 reverse_speakers = true;
2714 break;
2715 case 0:
2716 case 90:
2717 case 180:
2718 break;
2719 default:
2720 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07002721 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002722 }
Eric Laurent03f09432014-03-25 18:09:11 -07002723 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07002724 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002725 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002726 }
2727
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002728 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
2729 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002730 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002731 }
2732
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08002733 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002734done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002736 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07002737 ALOGV("%s: exit with code(%d)", __func__, status);
2738 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739}
2740
2741static char* adev_get_parameters(const struct audio_hw_device *dev,
2742 const char *keys)
2743{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002744 struct audio_device *adev = (struct audio_device *)dev;
2745 struct str_parms *reply = str_parms_create();
2746 struct str_parms *query = str_parms_create_str(keys);
2747 char *str;
2748
2749 pthread_mutex_lock(&adev->lock);
2750
2751 voice_get_parameters(adev, query, reply);
2752 str = str_parms_to_str(reply);
2753 str_parms_destroy(query);
2754 str_parms_destroy(reply);
2755
2756 pthread_mutex_unlock(&adev->lock);
2757 ALOGV("%s: exit: returns - %s", __func__, str);
2758 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759}
2760
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002761static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762{
2763 return 0;
2764}
2765
Haynes Mathew George5191a852013-09-11 14:19:36 -07002766static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
2767{
2768 int ret;
2769 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002770
Eric Laurent4cc4ce12014-09-10 13:21:01 -05002771 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
2772
Haynes Mathew George5191a852013-09-11 14:19:36 -07002773 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002774 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07002775 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002776
Haynes Mathew George5191a852013-09-11 14:19:36 -07002777 return ret;
2778}
2779
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002780static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781{
2782 return -ENOSYS;
2783}
2784
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002785static int adev_get_master_volume(struct audio_hw_device *dev __unused,
2786 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002787{
2788 return -ENOSYS;
2789}
2790
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002791static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792{
2793 return -ENOSYS;
2794}
2795
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002796static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002797{
2798 return -ENOSYS;
2799}
2800
2801static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2802{
2803 struct audio_device *adev = (struct audio_device *)dev;
2804
2805 pthread_mutex_lock(&adev->lock);
2806 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07002807 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07002809 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
2810 voice_is_in_call(adev)) {
2811 voice_stop_call(adev);
2812 adev->current_call_output = NULL;
2813 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002814 }
2815 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002816
2817 audio_extn_extspk_set_mode(adev->extspk, mode);
2818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 return 0;
2820}
2821
2822static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2823{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002824 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002826
Eric Laurent2bafff12016-03-17 12:17:23 -07002827 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002828 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002829 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002830 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00002831 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002832
2833 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834}
2835
2836static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2837{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002838 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839 return 0;
2840}
2841
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002842static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002843 const struct audio_config *config)
2844{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002845 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002846
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002847 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
2848 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849}
2850
2851static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002852 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002853 audio_devices_t devices,
2854 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002855 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07002856 audio_input_flags_t flags,
2857 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05002858 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002859{
2860 struct audio_device *adev = (struct audio_device *)dev;
2861 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002862 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002863 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002864 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865
Eric Laurent994a6932013-07-17 11:51:42 -07002866 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002867 *stream_in = NULL;
2868 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2869 return -EINVAL;
2870
2871 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
2872
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002873 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07002874 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 in->stream.common.get_sample_rate = in_get_sample_rate;
2877 in->stream.common.set_sample_rate = in_set_sample_rate;
2878 in->stream.common.get_buffer_size = in_get_buffer_size;
2879 in->stream.common.get_channels = in_get_channels;
2880 in->stream.common.get_format = in_get_format;
2881 in->stream.common.set_format = in_set_format;
2882 in->stream.common.standby = in_standby;
2883 in->stream.common.dump = in_dump;
2884 in->stream.common.set_parameters = in_set_parameters;
2885 in->stream.common.get_parameters = in_get_parameters;
2886 in->stream.common.add_audio_effect = in_add_audio_effect;
2887 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2888 in->stream.set_gain = in_set_gain;
2889 in->stream.read = in_read;
2890 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08002891 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892
2893 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002894 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002895 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002896 in->standby = 1;
2897 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002898 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002899 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002900
vivek mehta57ff9b52016-04-28 14:13:08 -07002901 // restrict 24 bit capture for unprocessed source only
2902 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
2903 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07002904 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07002905 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
2906 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
2907 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
2908 bool ret_error = false;
2909 /* 24 bit is restricted to UNPROCESSED source only,also format supported
2910 from HAL is 8_24
2911 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
2912 8_24 return error indicating supported format is 8_24
2913 *> In case of any other source requesting 24 bit or float return error
2914 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07002915
vivek mehta57ff9b52016-04-28 14:13:08 -07002916 on error flinger will retry with supported format passed
2917 */
2918 if (source != AUDIO_SOURCE_UNPROCESSED) {
2919 config->format = AUDIO_FORMAT_PCM_16_BIT;
2920 ret_error = true;
2921 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
2922 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
2923 ret_error = true;
2924 }
2925
2926 if (ret_error) {
2927 ret = -EINVAL;
2928 goto err_open;
2929 }
vivek mehta4ed66e62016-04-15 23:33:34 -07002930 }
2931
vivek mehta57ff9b52016-04-28 14:13:08 -07002932 in->format = config->format;
2933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002935 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
2936 if (config->sample_rate == 0)
2937 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2938 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2939 config->sample_rate != 8000) {
2940 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2941 ret = -EINVAL;
2942 goto err_open;
2943 }
vivek mehta4ed66e62016-04-15 23:33:34 -07002944
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002945 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2946 config->format = AUDIO_FORMAT_PCM_16_BIT;
2947 ret = -EINVAL;
2948 goto err_open;
2949 }
2950
2951 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
2952 in->config = pcm_config_afe_proxy_record;
2953 } else {
2954 in->usecase = USECASE_AUDIO_RECORD;
2955 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
2956 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
2957 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07002958#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002959 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07002960#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08002961 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002962 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002963
Haynes Mathew George03c40102016-01-29 17:57:48 -08002964 in->config = in->realtime ? pcm_config_audio_capture_rt :
2965 pcm_config_audio_capture;
2966
vivek mehta4ed66e62016-04-15 23:33:34 -07002967 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
2968 in->config.format = PCM_FORMAT_S24_LE;
2969
Haynes Mathew George03c40102016-01-29 17:57:48 -08002970 if (!in->realtime) {
2971 frame_size = audio_stream_in_frame_size(&in->stream);
2972 buffer_size = get_input_buffer_size(config->sample_rate,
2973 config->format,
2974 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002975 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08002976 in->config.period_size = buffer_size / frame_size;
2977 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002978 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002979
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002980 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002981 if (in->realtime) {
2982 in->af_period_multiplier = af_period_multiplier;
2983 } else {
2984 in->config.rate = config->sample_rate;
2985 in->af_period_multiplier = 1;
2986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002987
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002988 /* This stream could be for sound trigger lab,
2989 get sound trigger pcm if present */
2990 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002991
2992 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002993 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002994 return 0;
2995
2996err_open:
2997 free(in);
2998 *stream_in = NULL;
2999 return ret;
3000}
3001
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003002static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003 struct audio_stream_in *stream)
3004{
Eric Laurent994a6932013-07-17 11:51:42 -07003005 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003007 in_standby(&stream->common);
3008 free(stream);
3009
3010 return;
3011}
3012
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003013static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014{
3015 return 0;
3016}
3017
Andy Hung31aca912014-03-20 17:14:59 -07003018/* verifies input and output devices and their capabilities.
3019 *
3020 * This verification is required when enabling extended bit-depth or
3021 * sampling rates, as not all qcom products support it.
3022 *
3023 * Suitable for calling only on initialization such as adev_open().
3024 * It fills the audio_device use_case_table[] array.
3025 *
3026 * Has a side-effect that it needs to configure audio routing / devices
3027 * in order to power up the devices and read the device parameters.
3028 * It does not acquire any hw device lock. Should restore the devices
3029 * back to "normal state" upon completion.
3030 */
3031static int adev_verify_devices(struct audio_device *adev)
3032{
3033 /* enumeration is a bit difficult because one really wants to pull
3034 * the use_case, device id, etc from the hidden pcm_device_table[].
3035 * In this case there are the following use cases and device ids.
3036 *
3037 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3038 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3039 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3040 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3041 * [USECASE_AUDIO_RECORD] = {0, 0},
3042 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3043 * [USECASE_VOICE_CALL] = {2, 2},
3044 *
3045 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3046 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3047 */
3048
3049 /* should be the usecases enabled in adev_open_input_stream() */
3050 static const int test_in_usecases[] = {
3051 USECASE_AUDIO_RECORD,
3052 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3053 };
3054 /* should be the usecases enabled in adev_open_output_stream()*/
3055 static const int test_out_usecases[] = {
3056 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3057 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3058 };
3059 static const usecase_type_t usecase_type_by_dir[] = {
3060 PCM_PLAYBACK,
3061 PCM_CAPTURE,
3062 };
3063 static const unsigned flags_by_dir[] = {
3064 PCM_OUT,
3065 PCM_IN,
3066 };
3067
3068 size_t i;
3069 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003070 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003071 char info[512]; /* for possible debug info */
3072
3073 for (dir = 0; dir < 2; ++dir) {
3074 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3075 const unsigned flags_dir = flags_by_dir[dir];
3076 const size_t testsize =
3077 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3078 const int *testcases =
3079 dir ? test_in_usecases : test_out_usecases;
3080 const audio_devices_t audio_device =
3081 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3082
3083 for (i = 0; i < testsize; ++i) {
3084 const audio_usecase_t audio_usecase = testcases[i];
3085 int device_id;
3086 snd_device_t snd_device;
3087 struct pcm_params **pparams;
3088 struct stream_out out;
3089 struct stream_in in;
3090 struct audio_usecase uc_info;
3091 int retval;
3092
3093 pparams = &adev->use_case_table[audio_usecase];
3094 pcm_params_free(*pparams); /* can accept null input */
3095 *pparams = NULL;
3096
3097 /* find the device ID for the use case (signed, for error) */
3098 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3099 if (device_id < 0)
3100 continue;
3101
3102 /* prepare structures for device probing */
3103 memset(&uc_info, 0, sizeof(uc_info));
3104 uc_info.id = audio_usecase;
3105 uc_info.type = usecase_type;
3106 if (dir) {
3107 adev->active_input = &in;
3108 memset(&in, 0, sizeof(in));
3109 in.device = audio_device;
3110 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3111 uc_info.stream.in = &in;
3112 } else {
3113 adev->active_input = NULL;
3114 }
3115 memset(&out, 0, sizeof(out));
3116 out.devices = audio_device; /* only field needed in select_devices */
3117 uc_info.stream.out = &out;
3118 uc_info.devices = audio_device;
3119 uc_info.in_snd_device = SND_DEVICE_NONE;
3120 uc_info.out_snd_device = SND_DEVICE_NONE;
3121 list_add_tail(&adev->usecase_list, &uc_info.list);
3122
3123 /* select device - similar to start_(in/out)put_stream() */
3124 retval = select_devices(adev, audio_usecase);
3125 if (retval >= 0) {
3126 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3127#if LOG_NDEBUG == 0
3128 if (*pparams) {
3129 ALOGV("%s: (%s) card %d device %d", __func__,
3130 dir ? "input" : "output", card_id, device_id);
3131 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003132 } else {
3133 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3134 }
3135#endif
3136 }
3137
3138 /* deselect device - similar to stop_(in/out)put_stream() */
3139 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003140 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003141 /* 2. Disable the rx device */
3142 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003143 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003144 list_remove(&uc_info.list);
3145 }
3146 }
3147 adev->active_input = NULL; /* restore adev state */
3148 return 0;
3149}
3150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003151static int adev_close(hw_device_t *device)
3152{
Andy Hung31aca912014-03-20 17:14:59 -07003153 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003154 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003155
3156 if (!adev)
3157 return 0;
3158
3159 pthread_mutex_lock(&adev_init_lock);
3160
3161 if ((--audio_device_ref_count) == 0) {
3162 audio_route_free(adev->audio_route);
3163 free(adev->snd_dev_ref_cnt);
3164 platform_deinit(adev->platform);
3165 audio_extn_extspk_deinit(adev->extspk);
3166 audio_extn_sound_trigger_deinit(adev);
3167 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3168 pcm_params_free(adev->use_case_table[i]);
3169 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003170 if (adev->adm_deinit)
3171 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003172 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003173 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003174
3175 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177 return 0;
3178}
3179
Glenn Kasten4f993392014-05-14 07:30:48 -07003180/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3181 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3182 * just that it _might_ work.
3183 */
3184static int period_size_is_plausible_for_low_latency(int period_size)
3185{
3186 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003187 case 48:
3188 case 96:
3189 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003190 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003191 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003192 case 240:
3193 case 320:
3194 case 480:
3195 return 1;
3196 default:
3197 return 0;
3198 }
3199}
3200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003201static int adev_open(const hw_module_t *module, const char *name,
3202 hw_device_t **device)
3203{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003204 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205
Eric Laurent2bafff12016-03-17 12:17:23 -07003206 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003208 pthread_mutex_lock(&adev_init_lock);
3209 if (audio_device_ref_count != 0) {
3210 *device = &adev->device.common;
3211 audio_device_ref_count++;
3212 ALOGV("%s: returning existing instance of adev", __func__);
3213 ALOGV("%s: exit", __func__);
3214 pthread_mutex_unlock(&adev_init_lock);
3215 return 0;
3216 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003217 adev = calloc(1, sizeof(struct audio_device));
3218
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003219 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3222 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3223 adev->device.common.module = (struct hw_module_t *)module;
3224 adev->device.common.close = adev_close;
3225
3226 adev->device.init_check = adev_init_check;
3227 adev->device.set_voice_volume = adev_set_voice_volume;
3228 adev->device.set_master_volume = adev_set_master_volume;
3229 adev->device.get_master_volume = adev_get_master_volume;
3230 adev->device.set_master_mute = adev_set_master_mute;
3231 adev->device.get_master_mute = adev_get_master_mute;
3232 adev->device.set_mode = adev_set_mode;
3233 adev->device.set_mic_mute = adev_set_mic_mute;
3234 adev->device.get_mic_mute = adev_get_mic_mute;
3235 adev->device.set_parameters = adev_set_parameters;
3236 adev->device.get_parameters = adev_get_parameters;
3237 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3238 adev->device.open_output_stream = adev_open_output_stream;
3239 adev->device.close_output_stream = adev_close_output_stream;
3240 adev->device.open_input_stream = adev_open_input_stream;
3241 adev->device.close_input_stream = adev_close_input_stream;
3242 adev->device.dump = adev_dump;
3243
3244 /* Set the default route before the PCM stream is opened */
3245 pthread_mutex_lock(&adev->lock);
3246 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003247 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003248 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003249 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003250 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003251 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003252 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003253 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003254 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 pthread_mutex_unlock(&adev->lock);
3256
3257 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003258 adev->platform = platform_init(adev);
3259 if (!adev->platform) {
3260 free(adev->snd_dev_ref_cnt);
3261 free(adev);
3262 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3263 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003264 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003265 return -EINVAL;
3266 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003267
Eric Laurent0499d4f2014-08-25 22:39:29 -05003268 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003269 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003270
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003271 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3272 if (adev->visualizer_lib == NULL) {
3273 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3274 } else {
3275 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3276 adev->visualizer_start_output =
3277 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3278 "visualizer_hal_start_output");
3279 adev->visualizer_stop_output =
3280 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3281 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003282 }
3283
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003284 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3285 if (adev->offload_effects_lib == NULL) {
3286 ALOGW("%s: DLOPEN failed for %s", __func__,
3287 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3288 } else {
3289 ALOGV("%s: DLOPEN successful for %s", __func__,
3290 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3291 adev->offload_effects_start_output =
3292 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3293 "offload_effects_bundle_hal_start_output");
3294 adev->offload_effects_stop_output =
3295 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3296 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003297 }
3298
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003299 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3300 if (adev->adm_lib == NULL) {
3301 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3302 } else {
3303 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3304 adev->adm_init = (adm_init_t)
3305 dlsym(adev->adm_lib, "adm_init");
3306 adev->adm_deinit = (adm_deinit_t)
3307 dlsym(adev->adm_lib, "adm_deinit");
3308 adev->adm_register_input_stream = (adm_register_input_stream_t)
3309 dlsym(adev->adm_lib, "adm_register_input_stream");
3310 adev->adm_register_output_stream = (adm_register_output_stream_t)
3311 dlsym(adev->adm_lib, "adm_register_output_stream");
3312 adev->adm_deregister_stream = (adm_deregister_stream_t)
3313 dlsym(adev->adm_lib, "adm_deregister_stream");
3314 adev->adm_request_focus = (adm_request_focus_t)
3315 dlsym(adev->adm_lib, "adm_request_focus");
3316 adev->adm_abandon_focus = (adm_abandon_focus_t)
3317 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003318 adev->adm_set_config = (adm_set_config_t)
3319 dlsym(adev->adm_lib, "adm_set_config");
3320 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3321 dlsym(adev->adm_lib, "adm_request_focus_v2");
3322 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3323 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3324 adev->adm_on_routing_change = (adm_on_routing_change_t)
3325 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003326 }
3327
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003328 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003329 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003332
Andy Hung31aca912014-03-20 17:14:59 -07003333 if (k_enable_extended_precision)
3334 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335
Glenn Kasten4f993392014-05-14 07:30:48 -07003336 char value[PROPERTY_VALUE_MAX];
3337 int trial;
3338 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3339 trial = atoi(value);
3340 if (period_size_is_plausible_for_low_latency(trial)) {
3341 pcm_config_low_latency.period_size = trial;
3342 pcm_config_low_latency.start_threshold = trial / 4;
3343 pcm_config_low_latency.avail_min = trial / 4;
3344 configured_low_latency_capture_period_size = trial;
3345 }
3346 }
3347 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3348 trial = atoi(value);
3349 if (period_size_is_plausible_for_low_latency(trial)) {
3350 configured_low_latency_capture_period_size = trial;
3351 }
3352 }
3353
vivek mehta1a9b7c02015-06-25 11:49:38 -07003354 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003355
3356 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3357 af_period_multiplier = atoi(value);
3358 if (af_period_multiplier < 0) {
3359 af_period_multiplier = 2;
3360 } else if (af_period_multiplier > 4) {
3361 af_period_multiplier = 4;
3362 }
3363 ALOGV("new period_multiplier = %d", af_period_multiplier);
3364 }
3365
vivek mehta1a9b7c02015-06-25 11:49:38 -07003366 pthread_mutex_unlock(&adev_init_lock);
3367
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003368 if (adev->adm_init)
3369 adev->adm_data = adev->adm_init();
3370
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003371 audio_extn_perf_lock_init();
3372
Eric Laurent2bafff12016-03-17 12:17:23 -07003373 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 return 0;
3375}
3376
3377static struct hw_module_methods_t hal_module_methods = {
3378 .open = adev_open,
3379};
3380
3381struct audio_module HAL_MODULE_INFO_SYM = {
3382 .common = {
3383 .tag = HARDWARE_MODULE_TAG,
3384 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3385 .hal_api_version = HARDWARE_HAL_API_VERSION,
3386 .id = AUDIO_HARDWARE_MODULE_ID,
3387 .name = "QCOM Audio HAL",
3388 .author = "Code Aurora Forum",
3389 .methods = &hal_module_methods,
3390 },
3391};