blob: 5b449bb68647ad1a6933f6215d0d71436a227e75 [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
Marco Nelissen32093f52015-04-08 15:14:02 -070057#define COMPRESS_OFFLOAD_FRAGMENT_SIZE (256 * 1024)
Marco Nelissen94c33a02015-05-12 09:11:34 -070058// 2 buffers causes problems with high bitrate files
59#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 3
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070060/* ToDo: Check and update a proper value in msec */
61#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 96
62#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
63
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -070064#define PROXY_OPEN_RETRY_COUNT 100
65#define PROXY_OPEN_WAIT_TIME 20
66
vivek mehtadae44712015-07-27 14:13:18 -070067#define MIN_CHANNEL_COUNT 1
68#define DEFAULT_CHANNEL_COUNT 2
69
Jean-Michel Trivic0750692015-10-12 12:12:32 -070070#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
71#define MAX_CHANNEL_COUNT 1
72#else
vivek mehtadae44712015-07-27 14:13:18 -070073#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
74#define XSTR(x) STR(x)
75#define STR(x) #x
Jean-Michel Trivic0750692015-10-12 12:12:32 -070076#endif
vivek mehtadae44712015-07-27 14:13:18 -070077
Haynes Mathew George03c40102016-01-29 17:57:48 -080078#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
79
Glenn Kasten4f993392014-05-14 07:30:48 -070080static unsigned int configured_low_latency_capture_period_size =
81 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
82
Andy Hung31aca912014-03-20 17:14:59 -070083/* This constant enables extended precision handling.
84 * TODO The flag is off until more testing is done.
85 */
86static const bool k_enable_extended_precision = false;
87
Eric Laurentb23d5282013-05-14 15:27:20 -070088struct pcm_config pcm_config_deep_buffer = {
vivek mehtadae44712015-07-27 14:13:18 -070089 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -070090 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
91 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
92 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
93 .format = PCM_FORMAT_S16_LE,
94 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
95 .stop_threshold = INT_MAX,
96 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
97};
98
99struct pcm_config pcm_config_low_latency = {
vivek mehtadae44712015-07-27 14:13:18 -0700100 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700101 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
102 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
103 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
104 .format = PCM_FORMAT_S16_LE,
105 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
106 .stop_threshold = INT_MAX,
107 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
108};
109
Haynes Mathew George03c40102016-01-29 17:57:48 -0800110static int af_period_multiplier = 4;
111struct pcm_config pcm_config_rt = {
112 .channels = DEFAULT_CHANNEL_COUNT,
113 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
114 .period_size = ULL_PERIOD_SIZE, //1 ms
115 .period_count = 512, //=> buffer size is 512ms
116 .format = PCM_FORMAT_S16_LE,
117 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
118 .stop_threshold = INT_MAX,
119 .silence_threshold = 0,
120 .silence_size = 0,
121 .avail_min = ULL_PERIOD_SIZE, //1 ms
122};
123
Eric Laurentb23d5282013-05-14 15:27:20 -0700124struct pcm_config pcm_config_hdmi_multi = {
125 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
126 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
127 .period_size = HDMI_MULTI_PERIOD_SIZE,
128 .period_count = HDMI_MULTI_PERIOD_COUNT,
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = 0,
131 .stop_threshold = INT_MAX,
132 .avail_min = 0,
133};
134
135struct pcm_config pcm_config_audio_capture = {
vivek mehtadae44712015-07-27 14:13:18 -0700136 .channels = DEFAULT_CHANNEL_COUNT,
Eric Laurentb23d5282013-05-14 15:27:20 -0700137 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
138 .format = PCM_FORMAT_S16_LE,
Eric Laurente2d2d1d2015-07-06 17:54:15 -0700139 .stop_threshold = INT_MAX,
140 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700141};
142
Haynes Mathew George03c40102016-01-29 17:57:48 -0800143struct pcm_config pcm_config_audio_capture_rt = {
144 .channels = DEFAULT_CHANNEL_COUNT,
145 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
146 .period_size = ULL_PERIOD_SIZE,
147 .period_count = 512,
148 .format = PCM_FORMAT_S16_LE,
149 .start_threshold = 0,
150 .stop_threshold = INT_MAX,
151 .silence_threshold = 0,
152 .silence_size = 0,
153 .avail_min = ULL_PERIOD_SIZE, //1 ms
154};
155
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700156#define AFE_PROXY_CHANNEL_COUNT 2
157#define AFE_PROXY_SAMPLING_RATE 48000
158
159#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
160#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
161
162struct pcm_config pcm_config_afe_proxy_playback = {
163 .channels = AFE_PROXY_CHANNEL_COUNT,
164 .rate = AFE_PROXY_SAMPLING_RATE,
165 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
166 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
167 .format = PCM_FORMAT_S16_LE,
168 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
169 .stop_threshold = INT_MAX,
170 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
171};
172
173#define AFE_PROXY_RECORD_PERIOD_SIZE 768
174#define AFE_PROXY_RECORD_PERIOD_COUNT 4
175
176struct pcm_config pcm_config_afe_proxy_record = {
177 .channels = AFE_PROXY_CHANNEL_COUNT,
178 .rate = AFE_PROXY_SAMPLING_RATE,
179 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
180 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
181 .format = PCM_FORMAT_S16_LE,
182 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
183 .stop_threshold = INT_MAX,
184 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
185};
186
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700187const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700188 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
189 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
190 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700191 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -0700192 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -0700193 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700194
Eric Laurentb23d5282013-05-14 15:27:20 -0700195 [USECASE_AUDIO_RECORD] = "audio-record",
196 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700197
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800198 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
199 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700200
Eric Laurentb23d5282013-05-14 15:27:20 -0700201 [USECASE_VOICE_CALL] = "voice-call",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700202 [USECASE_VOICE2_CALL] = "voice2-call",
203 [USECASE_VOLTE_CALL] = "volte-call",
204 [USECASE_QCHAT_CALL] = "qchat-call",
205 [USECASE_VOWLAN_CALL] = "vowlan-call",
vivek mehtaa51fd402016-02-04 19:49:33 -0800206 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
207 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700208
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700209 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
210 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
211
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700212 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
213 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700214};
215
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800216
217#define STRING_TO_ENUM(string) { #string, string }
218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800219struct string_to_enum {
220 const char *name;
221 uint32_t value;
222};
223
224static const struct string_to_enum out_channels_name_to_enum_table[] = {
225 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
226 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
227 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
228};
229
Haynes Mathew George5191a852013-09-11 14:19:36 -0700230static int set_voice_volume_l(struct audio_device *adev, float volume);
vivek mehta1a9b7c02015-06-25 11:49:38 -0700231static struct audio_device *adev = NULL;
232static pthread_mutex_t adev_init_lock;
233static unsigned int audio_device_ref_count;
234
Haynes Mathew George03c40102016-01-29 17:57:48 -0800235static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
236 int flags __unused)
237{
238 int dir = 0;
239 switch (uc_id) {
240 case USECASE_AUDIO_RECORD_LOW_LATENCY:
241 dir = 1;
242 case USECASE_AUDIO_PLAYBACK_ULL:
243 break;
244 default:
245 return false;
246 }
247
248 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
249 PCM_PLAYBACK : PCM_CAPTURE);
250 if (adev->adm_is_noirq_avail)
251 return adev->adm_is_noirq_avail(adev->adm_data,
252 adev->snd_card, dev_id, dir);
253 return false;
254}
255
256static void register_out_stream(struct stream_out *out)
257{
258 struct audio_device *adev = out->dev;
259 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
260 return;
261
262 if (!adev->adm_register_output_stream)
263 return;
264
265 adev->adm_register_output_stream(adev->adm_data,
266 out->handle,
267 out->flags);
268
269 if (!adev->adm_set_config)
270 return;
271
272 if (out->realtime) {
273 adev->adm_set_config(adev->adm_data,
274 out->handle,
275 out->pcm, &out->config);
276 }
277}
278
279static void register_in_stream(struct stream_in *in)
280{
281 struct audio_device *adev = in->dev;
282 if (!adev->adm_register_input_stream)
283 return;
284
285 adev->adm_register_input_stream(adev->adm_data,
286 in->capture_handle,
287 in->flags);
288
289 if (!adev->adm_set_config)
290 return;
291
292 if (in->realtime) {
293 adev->adm_set_config(adev->adm_data,
294 in->capture_handle,
295 in->pcm,
296 &in->config);
297 }
298}
299
300static void request_out_focus(struct stream_out *out, long ns)
301{
302 struct audio_device *adev = out->dev;
303
304 if (out->routing_change) {
305 out->routing_change = false;
306 if (adev->adm_on_routing_change)
307 adev->adm_on_routing_change(adev->adm_data, out->handle);
308 }
309
310 if (adev->adm_request_focus_v2) {
311 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
312 } else if (adev->adm_request_focus) {
313 adev->adm_request_focus(adev->adm_data, out->handle);
314 }
315}
316
317static void request_in_focus(struct stream_in *in, long ns)
318{
319 struct audio_device *adev = in->dev;
320
321 if (in->routing_change) {
322 in->routing_change = false;
323 if (adev->adm_on_routing_change)
324 adev->adm_on_routing_change(adev->adm_data, in->capture_handle);
325 }
326
327 if (adev->adm_request_focus_v2) {
328 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
329 } else if (adev->adm_request_focus) {
330 adev->adm_request_focus(adev->adm_data, in->capture_handle);
331 }
332}
333
334static void release_out_focus(struct stream_out *out, long ns __unused)
335{
336 struct audio_device *adev = out->dev;
337
338 if (adev->adm_abandon_focus)
339 adev->adm_abandon_focus(adev->adm_data, out->handle);
340}
341
342static void release_in_focus(struct stream_in *in, long ns __unused)
343{
344 struct audio_device *adev = in->dev;
345 if (adev->adm_abandon_focus)
346 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
347}
348
vivek mehta1a9b7c02015-06-25 11:49:38 -0700349__attribute__ ((visibility ("default")))
350bool audio_hw_send_gain_dep_calibration(int level) {
351 bool ret_val = false;
352 ALOGV("%s: enter ... ", __func__);
353
354 pthread_mutex_lock(&adev_init_lock);
355
356 if (adev != NULL && adev->platform != NULL) {
357 pthread_mutex_lock(&adev->lock);
358 ret_val = platform_send_gain_dep_cal(adev->platform, level);
359 pthread_mutex_unlock(&adev->lock);
360 } else {
361 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
362 }
363
364 pthread_mutex_unlock(&adev_init_lock);
365
366 ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
367 return ret_val;
368}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700369
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700370static bool is_supported_format(audio_format_t format)
371{
Eric Laurent8251ac82014-07-23 11:00:25 -0700372 switch (format) {
373 case AUDIO_FORMAT_MP3:
374 case AUDIO_FORMAT_AAC_LC:
375 case AUDIO_FORMAT_AAC_HE_V1:
376 case AUDIO_FORMAT_AAC_HE_V2:
377 return true;
378 default:
379 break;
380 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700381 return false;
382}
383
Haynes Mathew George03c40102016-01-29 17:57:48 -0800384static inline bool is_mmap_usecase(audio_usecase_t uc_id)
385{
386 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
387 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
388}
389
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700390static int get_snd_codec_id(audio_format_t format)
391{
392 int id = 0;
393
Eric Laurent8251ac82014-07-23 11:00:25 -0700394 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700395 case AUDIO_FORMAT_MP3:
396 id = SND_AUDIOCODEC_MP3;
397 break;
398 case AUDIO_FORMAT_AAC:
399 id = SND_AUDIOCODEC_AAC;
400 break;
401 default:
402 ALOGE("%s: Unsupported audio format", __func__);
403 }
404
405 return id;
406}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800407
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800408int enable_audio_route(struct audio_device *adev,
409 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800410{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700411 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800412 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800413
414 if (usecase == NULL)
415 return -EINVAL;
416
417 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
418
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800419 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700420 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800421 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700422 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800423
424 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500425 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Joe Onorato188b6222016-03-01 11:02:27 -0800426 ALOGV("%s: apply and update mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700427 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800429 ALOGV("%s: exit", __func__);
430 return 0;
431}
432
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800433int disable_audio_route(struct audio_device *adev,
434 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800435{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700436 snd_device_t snd_device;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437 char mixer_path[50];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800438
439 if (usecase == NULL)
440 return -EINVAL;
441
442 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700443 if (usecase->type == PCM_CAPTURE)
444 snd_device = usecase->in_snd_device;
445 else
446 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800447 strcpy(mixer_path, use_case_table[usecase->id]);
Ravi Kumar Alamanda299760a2013-11-01 17:29:09 -0500448 platform_add_backend_name(adev->platform, mixer_path, snd_device);
Joe Onorato188b6222016-03-01 11:02:27 -0800449 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700450 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800451
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800452 ALOGV("%s: exit", __func__);
453 return 0;
454}
455
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800456int enable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700457 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800458{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700459 int i, num_devices = 0;
460 snd_device_t new_snd_devices[2];
vivek mehtade4849c2016-03-03 17:23:38 -0800461 int ret_val = -EINVAL;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800462 if (snd_device < SND_DEVICE_MIN ||
463 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800464 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
vivek mehtade4849c2016-03-03 17:23:38 -0800465 goto on_error;
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800466 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700467
Ravi Kumar Alamanda5a95ff62015-08-31 17:42:44 -0700468 platform_send_audio_calibration(adev->platform, snd_device);
469
vivek mehtade4849c2016-03-03 17:23:38 -0800470 if (adev->snd_dev_ref_cnt[snd_device] >= 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700471 ALOGV("%s: snd_device(%d: %s) is already active",
Eric Laurentb23d5282013-05-14 15:27:20 -0700472 __func__, snd_device, platform_get_snd_device_name(snd_device));
vivek mehtade4849c2016-03-03 17:23:38 -0800473 goto on_success;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700474 }
475
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700476 /* due to the possibility of calibration overwrite between listen
477 and audio, notify sound trigger hal before audio calibration is sent */
478 audio_extn_sound_trigger_update_device_status(snd_device,
479 ST_EVENT_SND_DEVICE_BUSY);
480
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700481 if (audio_extn_spkr_prot_is_enabled())
482 audio_extn_spkr_prot_calib_cancel(adev);
483
zhaoyang yin4211fad2015-06-04 21:13:25 +0800484 audio_extn_dsm_feedback_enable(adev, snd_device, true);
485
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700486 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
487 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
488 audio_extn_spkr_prot_is_enabled()) {
489 if (audio_extn_spkr_prot_get_acdb_id(snd_device) < 0) {
vivek mehtade4849c2016-03-03 17:23:38 -0800490 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700491 }
492 if (audio_extn_spkr_prot_start_processing(snd_device)) {
493 ALOGE("%s: spkr_start_processing failed", __func__);
vivek mehtade4849c2016-03-03 17:23:38 -0800494 goto on_error;
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700495 }
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700496 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
497 for (i = 0; i < num_devices; i++) {
498 enable_snd_device(adev, new_snd_devices[i]);
499 }
vivek mehtab6506412015-08-07 16:55:17 -0700500 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700501 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800502 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
503 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
504 ALOGE(" %s: Invalid sound device returned", __func__);
505 goto on_error;
506 }
Ed Tam70b5c142016-03-21 19:14:29 -0700507
vivek mehtade4849c2016-03-03 17:23:38 -0800508 ALOGV("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
509 audio_route_apply_and_update_path(adev->audio_route, device_name);
510 }
511on_success:
512 adev->snd_dev_ref_cnt[snd_device]++;
513 ret_val = 0;
514on_error:
515 return ret_val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800516}
517
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800518int disable_snd_device(struct audio_device *adev,
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700519 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800520{
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700521 int i, num_devices = 0;
522 snd_device_t new_snd_devices[2];
523
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800524 if (snd_device < SND_DEVICE_MIN ||
525 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800526 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800527 return -EINVAL;
528 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700529 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
530 ALOGE("%s: device ref cnt is already 0", __func__);
531 return -EINVAL;
532 }
533 adev->snd_dev_ref_cnt[snd_device]--;
534 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
zhaoyang yin4211fad2015-06-04 21:13:25 +0800535 audio_extn_dsm_feedback_enable(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700536 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
537 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
538 audio_extn_spkr_prot_is_enabled()) {
539 audio_extn_spkr_prot_stop_processing(snd_device);
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700540 } else if (platform_can_split_snd_device(snd_device, &num_devices, new_snd_devices)) {
541 for (i = 0; i < num_devices; i++) {
542 disable_snd_device(adev, new_snd_devices[i]);
543 }
vivek mehtab6506412015-08-07 16:55:17 -0700544 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700545 } else {
vivek mehtade4849c2016-03-03 17:23:38 -0800546 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
547 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
548 ALOGE(" %s: Invalid sound device returned", __func__);
549 return -EINVAL;
550 }
551
552 ALOGV("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
553 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda63863002015-04-22 11:15:25 -0700554 }
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -0700555 audio_extn_sound_trigger_update_device_status(snd_device,
556 ST_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700557 }
vivek mehtab6506412015-08-07 16:55:17 -0700558
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800559 return 0;
560}
561
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700562static void check_and_route_playback_usecases(struct audio_device *adev,
563 struct audio_usecase *uc_info,
564 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700565{
566 struct listnode *node;
567 struct audio_usecase *usecase;
568 bool switch_device[AUDIO_USECASE_MAX];
569 int i, num_uc_to_switch = 0;
570
571 /*
572 * This function is to make sure that all the usecases that are active on
573 * the hardware codec backend are always routed to any one device that is
574 * handled by the hardware codec.
575 * For example, if low-latency and deep-buffer usecases are currently active
576 * on speaker and out_set_parameters(headset) is received on low-latency
577 * output, then we have to make sure deep-buffer is also switched to headset,
578 * because of the limitation that both the devices cannot be enabled
579 * at the same time as they share the same backend.
580 */
581 /* Disable all the usecases on the shared backend other than the
582 specified usecase */
583 for (i = 0; i < AUDIO_USECASE_MAX; i++)
584 switch_device[i] = false;
585
586 list_for_each(node, &adev->usecase_list) {
587 usecase = node_to_item(node, struct audio_usecase, list);
588 if (usecase->type != PCM_CAPTURE &&
589 usecase != uc_info &&
590 usecase->out_snd_device != snd_device &&
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700591 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND &&
592 platform_check_backends_match(snd_device, usecase->out_snd_device)) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700593 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
594 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700595 platform_get_snd_device_name(usecase->out_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700596 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700597 switch_device[usecase->id] = true;
598 num_uc_to_switch++;
599 }
600 }
601
602 if (num_uc_to_switch) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700603 list_for_each(node, &adev->usecase_list) {
604 usecase = node_to_item(node, struct audio_usecase, list);
605 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700606 disable_snd_device(adev, usecase->out_snd_device);
sangwon.jeon866d5ff2013-10-17 21:42:50 +0900607 }
608 }
609
610 list_for_each(node, &adev->usecase_list) {
611 usecase = node_to_item(node, struct audio_usecase, list);
612 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700613 enable_snd_device(adev, snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700614 }
615 }
616
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700617 /* Re-route all the usecases on the shared backend other than the
618 specified usecase to new snd devices */
619 list_for_each(node, &adev->usecase_list) {
620 usecase = node_to_item(node, struct audio_usecase, list);
621 /* Update the out_snd_device only before enabling the audio route */
622 if (switch_device[usecase->id] ) {
623 usecase->out_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700624 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625 }
626 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700627 }
628}
629
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700630static void check_and_route_capture_usecases(struct audio_device *adev,
631 struct audio_usecase *uc_info,
632 snd_device_t snd_device)
633{
634 struct listnode *node;
635 struct audio_usecase *usecase;
636 bool switch_device[AUDIO_USECASE_MAX];
637 int i, num_uc_to_switch = 0;
638
639 /*
640 * This function is to make sure that all the active capture usecases
641 * are always routed to the same input sound device.
642 * For example, if audio-record and voice-call usecases are currently
643 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
644 * is received for voice call then we have to make sure that audio-record
645 * usecase is also switched to earpiece i.e. voice-dmic-ef,
646 * because of the limitation that two devices cannot be enabled
647 * at the same time if they share the same backend.
648 */
649 for (i = 0; i < AUDIO_USECASE_MAX; i++)
650 switch_device[i] = false;
651
652 list_for_each(node, &adev->usecase_list) {
653 usecase = node_to_item(node, struct audio_usecase, list);
654 if (usecase->type != PCM_PLAYBACK &&
655 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700656 usecase->in_snd_device != snd_device &&
657 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700658 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
659 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700660 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700661 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700662 switch_device[usecase->id] = true;
663 num_uc_to_switch++;
664 }
665 }
666
667 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700668 list_for_each(node, &adev->usecase_list) {
669 usecase = node_to_item(node, struct audio_usecase, list);
670 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700671 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700672 }
673 }
674
675 list_for_each(node, &adev->usecase_list) {
676 usecase = node_to_item(node, struct audio_usecase, list);
677 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700678 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700679 }
680 }
681
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700682 /* Re-route all the usecases on the shared backend other than the
683 specified usecase to new snd devices */
684 list_for_each(node, &adev->usecase_list) {
685 usecase = node_to_item(node, struct audio_usecase, list);
686 /* Update the in_snd_device only before enabling the audio route */
687 if (switch_device[usecase->id] ) {
688 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700689 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700690 }
691 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700692 }
693}
694
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800695/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700696static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800697{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700698 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700699 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800700
701 switch (channels) {
702 /*
703 * Do not handle stereo output in Multi-channel cases
704 * Stereo case is handled in normal playback path
705 */
706 case 6:
707 ALOGV("%s: HDMI supports 5.1", __func__);
708 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
709 break;
710 case 8:
711 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
712 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
713 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
714 break;
715 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700716 ALOGE("HDMI does not support multi channel playback");
717 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800718 break;
719 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700720 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800721}
722
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700723static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
724{
725 struct audio_usecase *usecase;
726 struct listnode *node;
727
728 list_for_each(node, &adev->usecase_list) {
729 usecase = node_to_item(node, struct audio_usecase, list);
730 if (usecase->type == VOICE_CALL) {
731 ALOGV("%s: usecase id %d", __func__, usecase->id);
732 return usecase->id;
733 }
734 }
735 return USECASE_INVALID;
736}
737
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800738struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
739 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700740{
741 struct audio_usecase *usecase;
742 struct listnode *node;
743
744 list_for_each(node, &adev->usecase_list) {
745 usecase = node_to_item(node, struct audio_usecase, list);
746 if (usecase->id == uc_id)
747 return usecase;
748 }
749 return NULL;
750}
751
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800752int select_devices(struct audio_device *adev,
753 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800754{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800755 snd_device_t out_snd_device = SND_DEVICE_NONE;
756 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700757 struct audio_usecase *usecase = NULL;
758 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800759 struct audio_usecase *hfp_usecase = NULL;
760 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800761 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700762 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800763
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700764 usecase = get_usecase_from_list(adev, uc_id);
765 if (usecase == NULL) {
766 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
767 return -EINVAL;
768 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800769
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800770 if ((usecase->type == VOICE_CALL) ||
771 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700772 out_snd_device = platform_get_output_snd_device(adev->platform,
773 usecase->stream.out->devices);
774 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700775 usecase->devices = usecase->stream.out->devices;
776 } else {
777 /*
778 * If the voice call is active, use the sound devices of voice call usecase
779 * so that it would not result any device switch. All the usecases will
780 * be switched to new device when select_devices() is called for voice call
781 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700782 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700783 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700784 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700785 vc_usecase = get_usecase_from_list(adev,
786 get_voice_usecase_id_from_list(adev));
787 if ((vc_usecase != NULL) &&
788 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
789 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700790 in_snd_device = vc_usecase->in_snd_device;
791 out_snd_device = vc_usecase->out_snd_device;
792 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800793 } else if (audio_extn_hfp_is_active(adev)) {
794 hfp_ucid = audio_extn_hfp_get_usecase();
795 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
796 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
797 in_snd_device = hfp_usecase->in_snd_device;
798 out_snd_device = hfp_usecase->out_snd_device;
799 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700800 }
801 if (usecase->type == PCM_PLAYBACK) {
802 usecase->devices = usecase->stream.out->devices;
803 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700804 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700805 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700806 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700807 if (usecase->stream.out == adev->primary_output &&
808 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -0700809 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
810 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800811 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700812 select_devices(adev, adev->active_input->usecase);
813 }
814 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700815 } else if (usecase->type == PCM_CAPTURE) {
816 usecase->devices = usecase->stream.in->device;
817 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700818 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700819 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -0700820 if (adev->active_input &&
821 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
822 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800823 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -0700824 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
825 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
826 } else if (adev->primary_output) {
827 out_device = adev->primary_output->devices;
828 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700829 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700830 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700831 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700832 }
833 }
834
835 if (out_snd_device == usecase->out_snd_device &&
836 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800837 return 0;
838 }
839
Eric Laurent2bafff12016-03-17 12:17:23 -0700840 if (out_snd_device != SND_DEVICE_NONE &&
841 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
842 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
843 __func__,
844 use_case_table[uc_id],
845 adev->last_logged_snd_device[uc_id][0],
846 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
847 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
848 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
849 -1,
850 out_snd_device,
851 platform_get_snd_device_name(out_snd_device),
852 platform_get_snd_device_acdb_id(out_snd_device));
853 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
854 }
855 if (in_snd_device != SND_DEVICE_NONE &&
856 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
857 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
858 __func__,
859 use_case_table[uc_id],
860 adev->last_logged_snd_device[uc_id][1],
861 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
862 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
863 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
864 -1,
865 in_snd_device,
866 platform_get_snd_device_name(in_snd_device),
867 platform_get_snd_device_acdb_id(in_snd_device));
868 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
869 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800870
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800871 /*
872 * Limitation: While in call, to do a device switch we need to disable
873 * and enable both RX and TX devices though one of them is same as current
874 * device.
875 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700876 if ((usecase->type == VOICE_CALL) &&
877 (usecase->in_snd_device != SND_DEVICE_NONE) &&
878 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700879 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -0700880 /* Disable sidetone only if voice call already exists */
881 if (voice_is_call_state_active(adev))
882 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800883 }
884
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 /* Disable current sound devices */
886 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700887 disable_audio_route(adev, usecase);
888 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800889 }
890
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700891 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700892 disable_audio_route(adev, usecase);
893 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800894 }
895
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700896 /* Applicable only on the targets that has external modem.
897 * New device information should be sent to modem before enabling
898 * the devices to reduce in-call device switch time.
899 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700900 if ((usecase->type == VOICE_CALL) &&
901 (usecase->in_snd_device != SND_DEVICE_NONE) &&
902 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700903 status = platform_switch_voice_call_enable_device_config(adev->platform,
904 out_snd_device,
905 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700906 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700907
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700908 /* Enable new sound devices */
909 if (out_snd_device != SND_DEVICE_NONE) {
910 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700911 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700912 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800913 }
914
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700915 if (in_snd_device != SND_DEVICE_NONE) {
916 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700917 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700918 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700919
Eric Laurentb23d5282013-05-14 15:27:20 -0700920 if (usecase->type == VOICE_CALL)
921 status = platform_switch_voice_call_device_post(adev->platform,
922 out_snd_device,
923 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800924
sangwoo170731f2013-06-08 15:36:36 +0900925 usecase->in_snd_device = in_snd_device;
926 usecase->out_snd_device = out_snd_device;
927
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700928 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900929
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700930 /* Applicable only on the targets that has external modem.
931 * Enable device command should be sent to modem only after
932 * enabling voice call mixer controls
933 */
vivek mehta765eb642015-08-07 19:46:06 -0700934 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700935 status = platform_switch_voice_call_usecase_route_post(adev->platform,
936 out_snd_device,
937 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -0700938 /* Enable sidetone only if voice call already exists */
939 if (voice_is_call_state_active(adev))
940 voice_set_sidetone(adev, out_snd_device, true);
941 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800943 return status;
944}
945
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800946static int stop_input_stream(struct stream_in *in)
947{
948 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800949 struct audio_usecase *uc_info;
950 struct audio_device *adev = in->dev;
951
Eric Laurentc8400632013-02-14 19:04:54 -0800952 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800953
Eric Laurent994a6932013-07-17 11:51:42 -0700954 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700955 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800956 uc_info = get_usecase_from_list(adev, in->usecase);
957 if (uc_info == NULL) {
958 ALOGE("%s: Could not find the usecase (%d) in the list",
959 __func__, in->usecase);
960 return -EINVAL;
961 }
962
Eric Laurent150dbfe2013-02-27 14:31:02 -0800963 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700964 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700965
966 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700967 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800969 list_remove(&uc_info->list);
970 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800971
Eric Laurent994a6932013-07-17 11:51:42 -0700972 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973 return ret;
974}
975
976int start_input_stream(struct stream_in *in)
977{
978 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800979 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800980 struct audio_usecase *uc_info;
981 struct audio_device *adev = in->dev;
982
Eric Laurent994a6932013-07-17 11:51:42 -0700983 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Eric Laurentb23d5282013-05-14 15:27:20 -0700984 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985 if (in->pcm_device_id < 0) {
986 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
987 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800988 ret = -EINVAL;
989 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800990 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700991
992 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800993 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
994 uc_info->id = in->usecase;
995 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800996 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700997 uc_info->devices = in->device;
998 uc_info->in_snd_device = SND_DEVICE_NONE;
999 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001001 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001002
1003 audio_extn_perf_lock_acquire();
1004
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001005 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001006
Eric Laurentc8400632013-02-14 19:04:54 -08001007 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001008 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001009
Andy Hung6ebe5962016-01-15 17:46:57 -08001010 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001011 unsigned int pcm_open_retry_count = 0;
1012
1013 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1014 flags |= PCM_MMAP | PCM_NOIRQ;
1015 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001016 } else if (in->realtime) {
1017 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001019
1020 while (1) {
1021 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1022 flags, &in->config);
1023 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1024 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1025 if (in->pcm != NULL) {
1026 pcm_close(in->pcm);
1027 in->pcm = NULL;
1028 }
1029 if (pcm_open_retry_count-- == 0) {
1030 ret = -EIO;
1031 goto error_open;
1032 }
1033 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1034 continue;
1035 }
1036 break;
1037 }
1038
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001039 ALOGV("%s: pcm_prepare", __func__);
1040 ret = pcm_prepare(in->pcm);
1041 if (ret < 0) {
1042 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1043 pcm_close(in->pcm);
1044 in->pcm = NULL;
1045 goto error_open;
1046 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001047 register_in_stream(in);
1048 if (in->realtime) {
1049 ret = pcm_start(in->pcm);
1050 }
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001051 audio_extn_perf_lock_release();
1052
Eric Laurent994a6932013-07-17 11:51:42 -07001053 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001054
Eric Laurentc8400632013-02-14 19:04:54 -08001055 return ret;
1056
1057error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001059 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001060
1061error_config:
1062 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001063 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001064
1065 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001066}
1067
Eric Laurenta1478072015-09-21 17:21:52 -07001068void lock_input_stream(struct stream_in *in)
1069{
1070 pthread_mutex_lock(&in->pre_lock);
1071 pthread_mutex_lock(&in->lock);
1072 pthread_mutex_unlock(&in->pre_lock);
1073}
1074
1075void lock_output_stream(struct stream_out *out)
1076{
1077 pthread_mutex_lock(&out->pre_lock);
1078 pthread_mutex_lock(&out->lock);
1079 pthread_mutex_unlock(&out->pre_lock);
1080}
1081
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001082/* must be called with out->lock locked */
1083static int send_offload_cmd_l(struct stream_out* out, int command)
1084{
1085 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1086
1087 ALOGVV("%s %d", __func__, command);
1088
1089 cmd->cmd = command;
1090 list_add_tail(&out->offload_cmd_list, &cmd->node);
1091 pthread_cond_signal(&out->offload_cond);
1092 return 0;
1093}
1094
1095/* must be called iwth out->lock locked */
1096static void stop_compressed_output_l(struct stream_out *out)
1097{
1098 out->offload_state = OFFLOAD_STATE_IDLE;
1099 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001100 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001101 if (out->compr != NULL) {
1102 compress_stop(out->compr);
1103 while (out->offload_thread_blocked) {
1104 pthread_cond_wait(&out->cond, &out->lock);
1105 }
1106 }
1107}
1108
1109static void *offload_thread_loop(void *context)
1110{
1111 struct stream_out *out = (struct stream_out *) context;
1112 struct listnode *item;
1113
1114 out->offload_state = OFFLOAD_STATE_IDLE;
1115 out->playback_started = 0;
1116
1117 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1118 set_sched_policy(0, SP_FOREGROUND);
1119 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1120
1121 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001122 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001123 for (;;) {
1124 struct offload_cmd *cmd = NULL;
1125 stream_callback_event_t event;
1126 bool send_callback = false;
1127
1128 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1129 __func__, list_empty(&out->offload_cmd_list),
1130 out->offload_state);
1131 if (list_empty(&out->offload_cmd_list)) {
1132 ALOGV("%s SLEEPING", __func__);
1133 pthread_cond_wait(&out->offload_cond, &out->lock);
1134 ALOGV("%s RUNNING", __func__);
1135 continue;
1136 }
1137
1138 item = list_head(&out->offload_cmd_list);
1139 cmd = node_to_item(item, struct offload_cmd, node);
1140 list_remove(item);
1141
1142 ALOGVV("%s STATE %d CMD %d out->compr %p",
1143 __func__, out->offload_state, cmd->cmd, out->compr);
1144
1145 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1146 free(cmd);
1147 break;
1148 }
1149
1150 if (out->compr == NULL) {
1151 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001152 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001153 pthread_cond_signal(&out->cond);
1154 continue;
1155 }
1156 out->offload_thread_blocked = true;
1157 pthread_mutex_unlock(&out->lock);
1158 send_callback = false;
1159 switch(cmd->cmd) {
1160 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1161 compress_wait(out->compr, -1);
1162 send_callback = true;
1163 event = STREAM_CBK_EVENT_WRITE_READY;
1164 break;
1165 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001166 compress_next_track(out->compr);
1167 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001168 send_callback = true;
1169 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001170 /* Resend the metadata for next iteration */
1171 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001172 break;
1173 case OFFLOAD_CMD_DRAIN:
1174 compress_drain(out->compr);
1175 send_callback = true;
1176 event = STREAM_CBK_EVENT_DRAIN_READY;
1177 break;
1178 default:
1179 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1180 break;
1181 }
Eric Laurenta1478072015-09-21 17:21:52 -07001182 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001183 out->offload_thread_blocked = false;
1184 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001185 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001186 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001187 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001188 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001189 free(cmd);
1190 }
1191
1192 pthread_cond_signal(&out->cond);
1193 while (!list_empty(&out->offload_cmd_list)) {
1194 item = list_head(&out->offload_cmd_list);
1195 list_remove(item);
1196 free(node_to_item(item, struct offload_cmd, node));
1197 }
1198 pthread_mutex_unlock(&out->lock);
1199
1200 return NULL;
1201}
1202
1203static int create_offload_callback_thread(struct stream_out *out)
1204{
1205 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1206 list_init(&out->offload_cmd_list);
1207 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1208 offload_thread_loop, out);
1209 return 0;
1210}
1211
1212static int destroy_offload_callback_thread(struct stream_out *out)
1213{
Eric Laurenta1478072015-09-21 17:21:52 -07001214 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001215 stop_compressed_output_l(out);
1216 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1217
1218 pthread_mutex_unlock(&out->lock);
1219 pthread_join(out->offload_thread, (void **) NULL);
1220 pthread_cond_destroy(&out->offload_cond);
1221
1222 return 0;
1223}
1224
Eric Laurent07eeafd2013-10-06 12:52:49 -07001225static bool allow_hdmi_channel_config(struct audio_device *adev)
1226{
1227 struct listnode *node;
1228 struct audio_usecase *usecase;
1229 bool ret = true;
1230
1231 list_for_each(node, &adev->usecase_list) {
1232 usecase = node_to_item(node, struct audio_usecase, list);
1233 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1234 /*
1235 * If voice call is already existing, do not proceed further to avoid
1236 * disabling/enabling both RX and TX devices, CSD calls, etc.
1237 * Once the voice call done, the HDMI channels can be configured to
1238 * max channels of remaining use cases.
1239 */
1240 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001241 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001242 __func__);
1243 ret = false;
1244 break;
1245 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001246 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001247 "no change in HDMI channels", __func__);
1248 ret = false;
1249 break;
1250 }
1251 }
1252 }
1253 return ret;
1254}
1255
1256static int check_and_set_hdmi_channels(struct audio_device *adev,
1257 unsigned int channels)
1258{
1259 struct listnode *node;
1260 struct audio_usecase *usecase;
1261
1262 /* Check if change in HDMI channel config is allowed */
1263 if (!allow_hdmi_channel_config(adev))
1264 return 0;
1265
1266 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001267 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001268 return 0;
1269 }
1270
1271 platform_set_hdmi_channels(adev->platform, channels);
1272 adev->cur_hdmi_channels = channels;
1273
1274 /*
1275 * Deroute all the playback streams routed to HDMI so that
1276 * the back end is deactivated. Note that backend will not
1277 * be deactivated if any one stream is connected to it.
1278 */
1279 list_for_each(node, &adev->usecase_list) {
1280 usecase = node_to_item(node, struct audio_usecase, list);
1281 if (usecase->type == PCM_PLAYBACK &&
1282 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001283 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001284 }
1285 }
1286
1287 /*
1288 * Enable all the streams disabled above. Now the HDMI backend
1289 * will be activated with new channel configuration
1290 */
1291 list_for_each(node, &adev->usecase_list) {
1292 usecase = node_to_item(node, struct audio_usecase, list);
1293 if (usecase->type == PCM_PLAYBACK &&
1294 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001295 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001296 }
1297 }
1298
1299 return 0;
1300}
1301
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001302static int stop_output_stream(struct stream_out *out)
1303{
1304 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001305 struct audio_usecase *uc_info;
1306 struct audio_device *adev = out->dev;
1307
Eric Laurent994a6932013-07-17 11:51:42 -07001308 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001309 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 uc_info = get_usecase_from_list(adev, out->usecase);
1311 if (uc_info == NULL) {
1312 ALOGE("%s: Could not find the usecase (%d) in the list",
1313 __func__, out->usecase);
1314 return -EINVAL;
1315 }
1316
Haynes Mathew George41f86652014-06-17 14:22:15 -07001317 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1318 if (adev->visualizer_stop_output != NULL)
1319 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1320 if (adev->offload_effects_stop_output != NULL)
1321 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1322 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001323
Eric Laurent150dbfe2013-02-27 14:31:02 -08001324 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001325 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001326
1327 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001328 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001329
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001330 list_remove(&uc_info->list);
1331 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001332
Eric Laurent0499d4f2014-08-25 22:39:29 -05001333 audio_extn_extspk_update(adev->extspk);
1334
Eric Laurent07eeafd2013-10-06 12:52:49 -07001335 /* Must be called after removing the usecase from list */
1336 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1337 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1338
Eric Laurent994a6932013-07-17 11:51:42 -07001339 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340 return ret;
1341}
1342
1343int start_output_stream(struct stream_out *out)
1344{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001345 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001346 struct audio_usecase *uc_info;
1347 struct audio_device *adev = out->dev;
1348
Eric Laurent994a6932013-07-17 11:51:42 -07001349 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001350 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001351 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001352 if (out->pcm_device_id < 0) {
1353 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1354 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001355 ret = -EINVAL;
1356 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001357 }
1358
1359 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1360 uc_info->id = out->usecase;
1361 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001362 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001363 uc_info->devices = out->devices;
1364 uc_info->in_snd_device = SND_DEVICE_NONE;
1365 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001366
Eric Laurent07eeafd2013-10-06 12:52:49 -07001367 /* This must be called before adding this usecase to the list */
1368 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1369 check_and_set_hdmi_channels(adev, out->config.channels);
1370
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001371 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001372
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001373 audio_extn_perf_lock_acquire();
1374
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001375 select_devices(adev, out->usecase);
1376
Eric Laurent0499d4f2014-08-25 22:39:29 -05001377 audio_extn_extspk_update(adev->extspk);
1378
Andy Hung31aca912014-03-20 17:14:59 -07001379 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001380 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001381 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001382 unsigned int flags = PCM_OUT;
1383 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001384
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001385 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1386 flags |= PCM_MMAP | PCM_NOIRQ;
1387 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001388 } else if (out->realtime) {
1389 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001390 } else
1391 flags |= PCM_MONOTONIC;
1392
1393 while (1) {
1394 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1395 flags, &out->config);
1396 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1397 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1398 if (out->pcm != NULL) {
1399 pcm_close(out->pcm);
1400 out->pcm = NULL;
1401 }
1402 if (pcm_open_retry_count-- == 0) {
1403 ret = -EIO;
1404 goto error_open;
1405 }
1406 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1407 continue;
1408 }
1409 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001410 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001411 ALOGV("%s: pcm_prepare", __func__);
1412 if (pcm_is_ready(out->pcm)) {
1413 ret = pcm_prepare(out->pcm);
1414 if (ret < 0) {
1415 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1416 pcm_close(out->pcm);
1417 out->pcm = NULL;
1418 goto error_open;
1419 }
1420 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001421 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001422 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001423 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001424 COMPRESS_IN, &out->compr_config);
1425 if (out->compr && !is_compress_ready(out->compr)) {
1426 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1427 compress_close(out->compr);
1428 out->compr = NULL;
1429 ret = -EIO;
1430 goto error_open;
1431 }
1432 if (out->offload_callback)
1433 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001434
1435 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001436 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1437 if (adev->offload_effects_start_output != NULL)
1438 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001440 ret = 0;
1441 register_out_stream(out);
1442 if (out->realtime) {
1443 ret = pcm_start(out->pcm);
1444 }
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001445 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001446 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001447 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001448error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001449 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001451error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001452 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453}
1454
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455static int check_input_parameters(uint32_t sample_rate,
1456 audio_format_t format,
1457 int channel_count)
1458{
vivek mehtadae44712015-07-27 14:13:18 -07001459 if (format != AUDIO_FORMAT_PCM_16_BIT) {
1460 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1461 return -EINVAL;
1462 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001463
vivek mehtadae44712015-07-27 14:13:18 -07001464 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001465 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001466 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1467 return -EINVAL;
1468 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469
1470 switch (sample_rate) {
1471 case 8000:
1472 case 11025:
1473 case 12000:
1474 case 16000:
1475 case 22050:
1476 case 24000:
1477 case 32000:
1478 case 44100:
1479 case 48000:
1480 break;
1481 default:
vivek mehtadae44712015-07-27 14:13:18 -07001482 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001483 return -EINVAL;
1484 }
1485
1486 return 0;
1487}
1488
1489static size_t get_input_buffer_size(uint32_t sample_rate,
1490 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001491 int channel_count,
1492 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493{
1494 size_t size = 0;
1495
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001496 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1497 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001498
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001499 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001500 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001501 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001502 /* ToDo: should use frame_size computed based on the format and
1503 channel_count here. */
1504 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001505
Glenn Kasten4f993392014-05-14 07:30:48 -07001506 /* make sure the size is multiple of 32 bytes
1507 * At 48 kHz mono 16-bit PCM:
1508 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1509 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1510 */
1511 size += 0x1f;
1512 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001513
1514 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001515}
1516
1517static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1518{
1519 struct stream_out *out = (struct stream_out *)stream;
1520
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001521 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001522}
1523
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001524static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525{
1526 return -ENOSYS;
1527}
1528
1529static size_t out_get_buffer_size(const struct audio_stream *stream)
1530{
1531 struct stream_out *out = (struct stream_out *)stream;
1532
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001533 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1534 return out->compr_config.fragment_size;
1535 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001536 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001537 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538}
1539
1540static uint32_t out_get_channels(const struct audio_stream *stream)
1541{
1542 struct stream_out *out = (struct stream_out *)stream;
1543
1544 return out->channel_mask;
1545}
1546
1547static audio_format_t out_get_format(const struct audio_stream *stream)
1548{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001549 struct stream_out *out = (struct stream_out *)stream;
1550
1551 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552}
1553
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001554static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555{
1556 return -ENOSYS;
1557}
1558
1559static int out_standby(struct audio_stream *stream)
1560{
1561 struct stream_out *out = (struct stream_out *)stream;
1562 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001563
Eric Laurent994a6932013-07-17 11:51:42 -07001564 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001565 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001566
Eric Laurenta1478072015-09-21 17:21:52 -07001567 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001568 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001569 if (adev->adm_deregister_stream)
1570 adev->adm_deregister_stream(adev->adm_data, out->handle);
1571
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001572 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001574 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1575 if (out->pcm) {
1576 pcm_close(out->pcm);
1577 out->pcm = NULL;
1578 }
1579 } else {
1580 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001581 out->gapless_mdata.encoder_delay = 0;
1582 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001583 if (out->compr != NULL) {
1584 compress_close(out->compr);
1585 out->compr = NULL;
1586 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001587 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001588 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001589 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001590 }
1591 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001592 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001593 return 0;
1594}
1595
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001596static int out_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001597{
1598 return 0;
1599}
1600
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001601static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1602{
1603 int ret = 0;
1604 char value[32];
1605 struct compr_gapless_mdata tmp_mdata;
1606
1607 if (!out || !parms) {
1608 return -EINVAL;
1609 }
1610
1611 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1612 if (ret >= 0) {
1613 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1614 } else {
1615 return -EINVAL;
1616 }
1617
1618 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1619 if (ret >= 0) {
1620 tmp_mdata.encoder_padding = atoi(value);
1621 } else {
1622 return -EINVAL;
1623 }
1624
1625 out->gapless_mdata = tmp_mdata;
1626 out->send_new_metadata = 1;
1627 ALOGV("%s new encoder delay %u and padding %u", __func__,
1628 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1629
1630 return 0;
1631}
1632
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001633static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1634{
1635 return out == adev->primary_output || out == adev->voice_tx_output;
1636}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1639{
1640 struct stream_out *out = (struct stream_out *)stream;
1641 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001642 struct audio_usecase *usecase;
1643 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001644 struct str_parms *parms;
1645 char value[32];
1646 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001647 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001648 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649
Joe Onorato188b6222016-03-01 11:02:27 -08001650 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001651 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652 parms = str_parms_create_str(kvpairs);
1653 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1654 if (ret >= 0) {
1655 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001656 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001657 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001658
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001659 /*
1660 * When HDMI cable is unplugged the music playback is paused and
1661 * the policy manager sends routing=0. But the audioflinger
1662 * continues to write data until standby time (3sec).
1663 * As the HDMI core is turned off, the write gets blocked.
1664 * Avoid this by routing audio to speaker until standby.
1665 */
1666 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1667 val == AUDIO_DEVICE_NONE) {
1668 val = AUDIO_DEVICE_OUT_SPEAKER;
1669 }
1670
1671 /*
1672 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001673 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001674 * the select_devices(). But how do we undo this?
1675 *
1676 * For example, music playback is active on headset (deep-buffer usecase)
1677 * and if we go to ringtones and select a ringtone, low-latency usecase
1678 * will be started on headset+speaker. As we can't enable headset+speaker
1679 * and headset devices at the same time, select_devices() switches the music
1680 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1681 * So when the ringtone playback is completed, how do we undo the same?
1682 *
1683 * We are relying on the out_set_parameters() call on deep-buffer output,
1684 * once the ringtone playback is ended.
1685 * NOTE: We should not check if the current devices are same as new devices.
1686 * Because select_devices() must be called to switch back the music
1687 * playback to headset.
1688 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08001689 audio_devices_t new_dev = val;
1690 if (new_dev != AUDIO_DEVICE_NONE) {
1691 bool same_dev = out->devices == new_dev;
1692 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001693
Haynes Mathew George03c40102016-01-29 17:57:48 -08001694 if (!out->standby) {
1695 if (!same_dev) {
1696 ALOGV("update routing change");
1697 out->routing_change = true;
1698 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001699 select_devices(adev, out->usecase);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001700 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001701
Eric Laurenta7657192014-10-09 21:09:33 -07001702 if (output_drives_call(adev, out)) {
1703 if (!voice_is_in_call(adev)) {
1704 if (adev->mode == AUDIO_MODE_IN_CALL) {
1705 adev->current_call_output = out;
1706 ret = voice_start_call(adev);
1707 }
1708 } else {
1709 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001710 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07001711 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001712 }
1713 }
1714
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001715 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001716 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05001717
1718 /*handles device and call state changes*/
1719 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001721
1722 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1723 parse_compress_metadata(out, parms);
1724 }
1725
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001726 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07001727 ALOGV("%s: exit: code(%d)", __func__, status);
1728 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001729}
1730
1731static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1732{
1733 struct stream_out *out = (struct stream_out *)stream;
1734 struct str_parms *query = str_parms_create_str(keys);
1735 char *str;
1736 char value[256];
1737 struct str_parms *reply = str_parms_create();
1738 size_t i, j;
1739 int ret;
1740 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07001741 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1743 if (ret >= 0) {
1744 value[0] = '\0';
1745 i = 0;
1746 while (out->supported_channel_masks[i] != 0) {
1747 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1748 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1749 if (!first) {
1750 strcat(value, "|");
1751 }
1752 strcat(value, out_channels_name_to_enum_table[j].name);
1753 first = false;
1754 break;
1755 }
1756 }
1757 i++;
1758 }
1759 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1760 str = str_parms_to_str(reply);
1761 } else {
1762 str = strdup(keys);
1763 }
1764 str_parms_destroy(query);
1765 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001766 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767 return str;
1768}
1769
1770static uint32_t out_get_latency(const struct audio_stream_out *stream)
1771{
Haynes Mathew George03c40102016-01-29 17:57:48 -08001772 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 struct stream_out *out = (struct stream_out *)stream;
1774
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001775 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
1776 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001777 else if (out->realtime) {
1778 // since the buffer won't be filled up faster than realtime,
1779 // return a smaller number
1780 period_ms = (out->af_period_multiplier * out->config.period_size *
1781 1000) / (out->config.rate);
1782 hw_delay = platform_render_latency(out->usecase)/1000;
1783 return period_ms + hw_delay;
1784 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001785
1786 return (out->config.period_count * out->config.period_size * 1000) /
1787 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788}
1789
1790static int out_set_volume(struct audio_stream_out *stream, float left,
1791 float right)
1792{
Eric Laurenta9024de2013-04-04 09:19:12 -07001793 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001794 int volume[2];
1795
Eric Laurenta9024de2013-04-04 09:19:12 -07001796 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1797 /* only take left channel into account: the API is for stereo anyway */
1798 out->muted = (left == 0.0f);
1799 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001800 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1801 const char *mixer_ctl_name = "Compress Playback Volume";
1802 struct audio_device *adev = out->dev;
1803 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001804 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1805 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07001806 /* try with the control based on device id */
1807 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
1808 PCM_PLAYBACK);
1809 char ctl_name[128] = {0};
1810 snprintf(ctl_name, sizeof(ctl_name),
1811 "Compress Playback %d Volume", pcm_device_id);
1812 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
1813 if (!ctl) {
1814 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
1815 return -EINVAL;
1816 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001817 }
1818 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
1819 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
1820 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
1821 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07001822 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824 return -ENOSYS;
1825}
1826
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001827#ifdef NO_AUDIO_OUT
1828static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
1829 const void *buffer, size_t bytes)
1830{
1831 struct stream_out *out = (struct stream_out *)stream;
1832
1833 /* No Output device supported other than BT for playback.
1834 * Sleep for the amount of buffer duration
1835 */
Eric Laurenta1478072015-09-21 17:21:52 -07001836 lock_output_stream(out);
Uday Kishore Pasupuletib14d76b2015-11-13 20:06:37 -08001837 usleep(bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001838 out_get_sample_rate(&out->stream.common));
1839 pthread_mutex_unlock(&out->lock);
1840 return bytes;
1841}
1842#endif
1843
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001844static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1845 size_t bytes)
1846{
1847 struct stream_out *out = (struct stream_out *)stream;
1848 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07001849 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001850
Eric Laurenta1478072015-09-21 17:21:52 -07001851 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001853 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001854 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001855 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001856 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001857 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001858 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001859 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001860 goto exit;
1861 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001862 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001864 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001865 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
1866 if (out->send_new_metadata) {
1867 ALOGVV("send new gapless metadata");
1868 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
1869 out->send_new_metadata = 0;
1870 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08001871 unsigned int avail;
1872 struct timespec tstamp;
1873 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
1874 /* Do not limit write size if the available frames count is unknown */
1875 if (ret != 0) {
1876 avail = bytes;
1877 }
1878 if (avail == 0) {
1879 ret = 0;
1880 } else {
1881 if (avail > bytes) {
1882 avail = bytes;
1883 }
1884 ret = compress_write(out->compr, buffer, avail);
1885 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
1886 __func__, avail, ret);
1887 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001888
Eric Laurent6e895242013-09-05 16:10:57 -07001889 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001890 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
1891 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08001892 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001893 compress_start(out->compr);
1894 out->playback_started = 1;
1895 out->offload_state = OFFLOAD_STATE_PLAYING;
1896 }
1897 pthread_mutex_unlock(&out->lock);
1898 return ret;
1899 } else {
1900 if (out->pcm) {
1901 if (out->muted)
1902 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001903
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001904 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001905
Haynes Mathew George03c40102016-01-29 17:57:48 -08001906 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
1907 out->config.rate;
1908 request_out_focus(out, ns);
1909
1910 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
1911 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001912 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001913 else
1914 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001915
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001916 if (ret == 0)
1917 out->written += bytes / (out->config.channels * sizeof(short));
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001918
Haynes Mathew George03c40102016-01-29 17:57:48 -08001919 release_out_focus(out, ns);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001920 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001921 }
1922
1923exit:
1924 pthread_mutex_unlock(&out->lock);
1925
1926 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001927 if (out->pcm)
vivek mehta1a9b7c02015-06-25 11:49:38 -07001928 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929 out_standby(&out->stream.common);
Eric Laurentfdf296a2014-07-03 16:41:51 -07001930 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931 out_get_sample_rate(&out->stream.common));
1932 }
1933 return bytes;
1934}
1935
1936static int out_get_render_position(const struct audio_stream_out *stream,
1937 uint32_t *dsp_frames)
1938{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001939 struct stream_out *out = (struct stream_out *)stream;
1940 *dsp_frames = 0;
1941 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07001942 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001943 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08001944 unsigned long frames = 0;
1945 // TODO: check return value
1946 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
1947 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001948 ALOGVV("%s rendered frames %d sample_rate %d",
1949 __func__, *dsp_frames, out->sample_rate);
1950 }
1951 pthread_mutex_unlock(&out->lock);
1952 return 0;
1953 } else
1954 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955}
1956
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001957static int out_add_audio_effect(const struct audio_stream *stream __unused,
1958 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001959{
1960 return 0;
1961}
1962
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001963static int out_remove_audio_effect(const struct audio_stream *stream __unused,
1964 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965{
1966 return 0;
1967}
1968
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001969static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
1970 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001971{
1972 return -EINVAL;
1973}
1974
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001975static int out_get_presentation_position(const struct audio_stream_out *stream,
1976 uint64_t *frames, struct timespec *timestamp)
1977{
1978 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08001979 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07001980 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001981
Eric Laurenta1478072015-09-21 17:21:52 -07001982 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001983
Eric Laurent949a0892013-09-20 09:20:13 -07001984 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1985 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08001986 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07001987 compress_get_tstamp(out->compr, &dsp_frames,
1988 &out->sample_rate);
1989 ALOGVV("%s rendered frames %ld sample_rate %d",
1990 __func__, dsp_frames, out->sample_rate);
1991 *frames = dsp_frames;
1992 ret = 0;
1993 /* this is the best we can do */
1994 clock_gettime(CLOCK_MONOTONIC, timestamp);
1995 }
1996 } else {
1997 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07001998 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07001999 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2000 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002001 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002002 // This adjustment accounts for buffering after app processor.
2003 // It is based on estimated DSP latency per use case, rather than exact.
2004 signed_frames -=
2005 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2006
Eric Laurent949a0892013-09-20 09:20:13 -07002007 // It would be unusual for this value to be negative, but check just in case ...
2008 if (signed_frames >= 0) {
2009 *frames = signed_frames;
2010 ret = 0;
2011 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002012 }
2013 }
2014 }
2015
2016 pthread_mutex_unlock(&out->lock);
2017
2018 return ret;
2019}
2020
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002021static int out_set_callback(struct audio_stream_out *stream,
2022 stream_callback_t callback, void *cookie)
2023{
2024 struct stream_out *out = (struct stream_out *)stream;
2025
2026 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002027 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002028 out->offload_callback = callback;
2029 out->offload_cookie = cookie;
2030 pthread_mutex_unlock(&out->lock);
2031 return 0;
2032}
2033
2034static int out_pause(struct audio_stream_out* stream)
2035{
2036 struct stream_out *out = (struct stream_out *)stream;
2037 int status = -ENOSYS;
2038 ALOGV("%s", __func__);
2039 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002040 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002041 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2042 status = compress_pause(out->compr);
2043 out->offload_state = OFFLOAD_STATE_PAUSED;
2044 }
2045 pthread_mutex_unlock(&out->lock);
2046 }
2047 return status;
2048}
2049
2050static int out_resume(struct audio_stream_out* stream)
2051{
2052 struct stream_out *out = (struct stream_out *)stream;
2053 int status = -ENOSYS;
2054 ALOGV("%s", __func__);
2055 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2056 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002057 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002058 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2059 status = compress_resume(out->compr);
2060 out->offload_state = OFFLOAD_STATE_PLAYING;
2061 }
2062 pthread_mutex_unlock(&out->lock);
2063 }
2064 return status;
2065}
2066
2067static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2068{
2069 struct stream_out *out = (struct stream_out *)stream;
2070 int status = -ENOSYS;
2071 ALOGV("%s", __func__);
2072 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002073 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002074 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2075 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2076 else
2077 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2078 pthread_mutex_unlock(&out->lock);
2079 }
2080 return status;
2081}
2082
2083static int out_flush(struct audio_stream_out* stream)
2084{
2085 struct stream_out *out = (struct stream_out *)stream;
2086 ALOGV("%s", __func__);
2087 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002088 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002089 stop_compressed_output_l(out);
2090 pthread_mutex_unlock(&out->lock);
2091 return 0;
2092 }
2093 return -ENOSYS;
2094}
2095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096/** audio_stream_in implementation **/
2097static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2098{
2099 struct stream_in *in = (struct stream_in *)stream;
2100
2101 return in->config.rate;
2102}
2103
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002104static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002105{
2106 return -ENOSYS;
2107}
2108
2109static size_t in_get_buffer_size(const struct audio_stream *stream)
2110{
2111 struct stream_in *in = (struct stream_in *)stream;
2112
Haynes Mathew George03c40102016-01-29 17:57:48 -08002113 return in->config.period_size * in->af_period_multiplier *
2114 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002115}
2116
2117static uint32_t in_get_channels(const struct audio_stream *stream)
2118{
2119 struct stream_in *in = (struct stream_in *)stream;
2120
2121 return in->channel_mask;
2122}
2123
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002124static audio_format_t in_get_format(const struct audio_stream *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125{
2126 return AUDIO_FORMAT_PCM_16_BIT;
2127}
2128
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002129static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130{
2131 return -ENOSYS;
2132}
2133
2134static int in_standby(struct audio_stream *stream)
2135{
2136 struct stream_in *in = (struct stream_in *)stream;
2137 struct audio_device *adev = in->dev;
2138 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002139 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002140
2141 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002142
2143 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002144 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002145 audio_extn_sound_trigger_stop_lab(in);
2146 in->standby = true;
2147 }
2148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002149 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002150 if (adev->adm_deregister_stream)
2151 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2152
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002153 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002155 if (in->pcm) {
2156 pcm_close(in->pcm);
2157 in->pcm = NULL;
2158 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002159 adev->enable_voicerx = false;
2160 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002161 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002162 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 }
2164 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002165 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002166 return status;
2167}
2168
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002169static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002170{
2171 return 0;
2172}
2173
2174static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2175{
2176 struct stream_in *in = (struct stream_in *)stream;
2177 struct audio_device *adev = in->dev;
2178 struct str_parms *parms;
2179 char *str;
2180 char value[32];
2181 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002182 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002183
Eric Laurent994a6932013-07-17 11:51:42 -07002184 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185 parms = str_parms_create_str(kvpairs);
2186
2187 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2188
Eric Laurenta1478072015-09-21 17:21:52 -07002189 lock_input_stream(in);
2190
Eric Laurent150dbfe2013-02-27 14:31:02 -08002191 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002192 if (ret >= 0) {
2193 val = atoi(value);
2194 /* no audio source uses val == 0 */
2195 if ((in->source != val) && (val != 0)) {
2196 in->source = val;
2197 }
2198 }
2199
2200 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202 if (ret >= 0) {
2203 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002204 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002205 in->device = val;
2206 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002207 if (!in->standby) {
2208 ALOGV("update input routing change");
2209 in->routing_change = true;
2210 select_devices(adev, in->usecase);
2211 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 }
2213 }
2214
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002215 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002216 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217
2218 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002219 ALOGV("%s: exit: status(%d)", __func__, status);
2220 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002221}
2222
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002223static char* in_get_parameters(const struct audio_stream *stream __unused,
2224 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225{
2226 return strdup("");
2227}
2228
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002229static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002230{
2231 return 0;
2232}
2233
2234static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2235 size_t bytes)
2236{
2237 struct stream_in *in = (struct stream_in *)stream;
2238 struct audio_device *adev = in->dev;
2239 int i, ret = -1;
2240
Eric Laurenta1478072015-09-21 17:21:52 -07002241 lock_input_stream(in);
2242
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002243 if (in->is_st_session) {
2244 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2245 /* Read from sound trigger HAL */
2246 audio_extn_sound_trigger_read(in, buffer, bytes);
2247 pthread_mutex_unlock(&in->lock);
2248 return bytes;
2249 }
2250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002251 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002252 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002253 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002254 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 goto exit;
2257 }
2258 in->standby = 0;
2259 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260
Haynes Mathew George03c40102016-01-29 17:57:48 -08002261 //what's the duration requested by the client?
2262 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2263 in->config.rate;
2264 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002265
Haynes Mathew George03c40102016-01-29 17:57:48 -08002266 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002268 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002269 ret = pcm_mmap_read(in->pcm, buffer, bytes);
2270 } else
2271 ret = pcm_read(in->pcm, buffer, bytes);
Haynes Mathew George03c40102016-01-29 17:57:48 -08002272
2273 if (ret < 0) {
2274 ALOGE("Failed to read w/err %s", strerror(errno));
2275 ret = -errno;
2276 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277 }
2278
Haynes Mathew George03c40102016-01-29 17:57:48 -08002279 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002281 /*
2282 * Instead of writing zeroes here, we could trust the hardware
2283 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002284 * 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 -08002285 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002286 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002287 memset(buffer, 0, bytes);
2288
2289exit:
2290 pthread_mutex_unlock(&in->lock);
2291
2292 if (ret != 0) {
2293 in_standby(&in->stream.common);
2294 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002295 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002296 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002297 memset(buffer, 0, bytes); // clear return data
2298 }
2299 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002300 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002301 }
2302 return bytes;
2303}
2304
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002305static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002306{
2307 return 0;
2308}
2309
Andy Hung6ebe5962016-01-15 17:46:57 -08002310static int in_get_capture_position(const struct audio_stream_in *stream,
2311 int64_t *frames, int64_t *time)
2312{
2313 if (stream == NULL || frames == NULL || time == NULL) {
2314 return -EINVAL;
2315 }
2316 struct stream_in *in = (struct stream_in *)stream;
2317 int ret = -ENOSYS;
2318
2319 lock_input_stream(in);
2320 if (in->pcm) {
2321 struct timespec timestamp;
2322 unsigned int avail;
2323 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2324 *frames = in->frames_read + avail;
2325 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2326 ret = 0;
2327 }
2328 }
2329 pthread_mutex_unlock(&in->lock);
2330 return ret;
2331}
2332
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002333static int add_remove_audio_effect(const struct audio_stream *stream,
2334 effect_handle_t effect,
2335 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002336{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002337 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002338 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002339 int status = 0;
2340 effect_descriptor_t desc;
2341
2342 status = (*effect)->get_descriptor(effect, &desc);
2343 if (status != 0)
2344 return status;
2345
Eric Laurenta1478072015-09-21 17:21:52 -07002346 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002347 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002348 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002349 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002350 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002351 in->enable_aec != enable &&
2352 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2353 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002354 if (!enable)
2355 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002356 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2357 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2358 adev->enable_voicerx = enable;
2359 struct audio_usecase *usecase;
2360 struct listnode *node;
2361 list_for_each(node, &adev->usecase_list) {
2362 usecase = node_to_item(node, struct audio_usecase, list);
2363 if (usecase->type == PCM_PLAYBACK) {
2364 select_devices(adev, usecase->id);
2365 break;
2366 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002367 }
2368 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002369 if (!in->standby)
2370 select_devices(in->dev, in->usecase);
2371 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002372 if (in->enable_ns != enable &&
2373 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2374 in->enable_ns = enable;
2375 if (!in->standby)
2376 select_devices(in->dev, in->usecase);
2377 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002378 pthread_mutex_unlock(&in->dev->lock);
2379 pthread_mutex_unlock(&in->lock);
2380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381 return 0;
2382}
2383
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002384static int in_add_audio_effect(const struct audio_stream *stream,
2385 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386{
Eric Laurent994a6932013-07-17 11:51:42 -07002387 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002388 return add_remove_audio_effect(stream, effect, true);
2389}
2390
2391static int in_remove_audio_effect(const struct audio_stream *stream,
2392 effect_handle_t effect)
2393{
Eric Laurent994a6932013-07-17 11:51:42 -07002394 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002395 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002396}
2397
2398static int adev_open_output_stream(struct audio_hw_device *dev,
2399 audio_io_handle_t handle,
2400 audio_devices_t devices,
2401 audio_output_flags_t flags,
2402 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002403 struct audio_stream_out **stream_out,
2404 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002405{
2406 struct audio_device *adev = (struct audio_device *)dev;
2407 struct stream_out *out;
2408 int i, ret;
2409
Eric Laurent994a6932013-07-17 11:51:42 -07002410 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002411 __func__, config->sample_rate, config->channel_mask, devices, flags);
2412 *stream_out = NULL;
2413 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2414
2415 if (devices == AUDIO_DEVICE_NONE)
2416 devices = AUDIO_DEVICE_OUT_SPEAKER;
2417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002418 out->flags = flags;
2419 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002420 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002421 out->format = config->format;
2422 out->sample_rate = config->sample_rate;
2423 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2424 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002425 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426
2427 /* Init use case and pcm_config */
2428 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002429 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002431 pthread_mutex_lock(&adev->lock);
2432 ret = read_hdmi_channel_masks(out);
2433 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002434 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002435 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002436
2437 if (config->sample_rate == 0)
2438 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2439 if (config->channel_mask == 0)
2440 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002441 if (config->format == AUDIO_FORMAT_DEFAULT)
2442 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002443
2444 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002445 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002446 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2448 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002449 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002450 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002451 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002452 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2453 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2454 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2455 ALOGE("%s: Unsupported Offload information", __func__);
2456 ret = -EINVAL;
2457 goto error_open;
2458 }
2459 if (!is_supported_format(config->offload_info.format)) {
2460 ALOGE("%s: Unsupported audio format", __func__);
2461 ret = -EINVAL;
2462 goto error_open;
2463 }
2464
2465 out->compr_config.codec = (struct snd_codec *)
2466 calloc(1, sizeof(struct snd_codec));
2467
2468 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2469 if (config->offload_info.channel_mask)
2470 out->channel_mask = config->offload_info.channel_mask;
2471 else if (config->channel_mask)
2472 out->channel_mask = config->channel_mask;
2473 out->format = config->offload_info.format;
2474 out->sample_rate = config->offload_info.sample_rate;
2475
2476 out->stream.set_callback = out_set_callback;
2477 out->stream.pause = out_pause;
2478 out->stream.resume = out_resume;
2479 out->stream.drain = out_drain;
2480 out->stream.flush = out_flush;
2481
2482 out->compr_config.codec->id =
2483 get_snd_codec_id(config->offload_info.format);
2484 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2485 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002486 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002487 out->compr_config.codec->bit_rate =
2488 config->offload_info.bit_rate;
2489 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002490 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002491 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2492
2493 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2494 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002495
2496 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002497 create_offload_callback_thread(out);
2498 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2499 __func__, config->offload_info.version,
2500 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002501 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2502 if (config->sample_rate == 0)
2503 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2504 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2505 config->sample_rate != 8000) {
2506 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2507 ret = -EINVAL;
2508 goto error_open;
2509 }
2510 out->sample_rate = config->sample_rate;
2511 out->config.rate = config->sample_rate;
2512 if (config->format == AUDIO_FORMAT_DEFAULT)
2513 config->format = AUDIO_FORMAT_PCM_16_BIT;
2514 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2515 config->format = AUDIO_FORMAT_PCM_16_BIT;
2516 ret = -EINVAL;
2517 goto error_open;
2518 }
2519 out->format = config->format;
2520 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2521 out->config = pcm_config_afe_proxy_playback;
2522 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002524 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2525 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2526 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002527 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2528 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2529 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002530 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2531 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002532 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2533 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2534 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002535 } else {
2536 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2537 out->config = pcm_config_low_latency;
2538 }
2539 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2540 if (k_enable_extended_precision
2541 && pcm_params_format_test(adev->use_case_table[out->usecase],
2542 pcm_format_from_audio_format(config->format))) {
2543 out->config.format = pcm_format_from_audio_format(config->format);
2544 /* out->format already set to config->format */
2545 } else {
2546 /* deny the externally proposed config format
2547 * and use the one specified in audio_hw layer configuration.
2548 * Note: out->format is returned by out->stream.common.get_format()
2549 * and is used to set config->format in the code several lines below.
2550 */
2551 out->format = audio_format_from_pcm_format(out->config.format);
2552 }
2553 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002554 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07002556 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
2557 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002559 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002560 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002561 adev->primary_output = out;
2562 else {
2563 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002564 ret = -EEXIST;
2565 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002566 }
2567 }
2568
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002569 /* Check if this usecase is already existing */
2570 pthread_mutex_lock(&adev->lock);
2571 if (get_usecase_from_list(adev, out->usecase) != NULL) {
2572 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002574 ret = -EEXIST;
2575 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 }
2577 pthread_mutex_unlock(&adev->lock);
2578
2579 out->stream.common.get_sample_rate = out_get_sample_rate;
2580 out->stream.common.set_sample_rate = out_set_sample_rate;
2581 out->stream.common.get_buffer_size = out_get_buffer_size;
2582 out->stream.common.get_channels = out_get_channels;
2583 out->stream.common.get_format = out_get_format;
2584 out->stream.common.set_format = out_set_format;
2585 out->stream.common.standby = out_standby;
2586 out->stream.common.dump = out_dump;
2587 out->stream.common.set_parameters = out_set_parameters;
2588 out->stream.common.get_parameters = out_get_parameters;
2589 out->stream.common.add_audio_effect = out_add_audio_effect;
2590 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2591 out->stream.get_latency = out_get_latency;
2592 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002593#ifdef NO_AUDIO_OUT
2594 out->stream.write = out_write_for_no_output;
2595#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002597#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002598 out->stream.get_render_position = out_get_render_position;
2599 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002600 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601
Haynes Mathew George03c40102016-01-29 17:57:48 -08002602 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002604 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002605 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002607 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07002608 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002609 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 config->format = out->stream.common.get_format(&out->stream.common);
2612 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2613 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2614
2615 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002616 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002618
2619error_open:
2620 free(out);
2621 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07002622 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002623 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624}
2625
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002626static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 struct audio_stream_out *stream)
2628{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002629 struct stream_out *out = (struct stream_out *)stream;
2630 struct audio_device *adev = out->dev;
2631
Eric Laurent994a6932013-07-17 11:51:42 -07002632 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002634 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2635 destroy_offload_callback_thread(out);
2636
2637 if (out->compr_config.codec != NULL)
2638 free(out->compr_config.codec);
2639 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07002640
2641 if (adev->voice_tx_output == out)
2642 adev->voice_tx_output = NULL;
2643
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002644 pthread_cond_destroy(&out->cond);
2645 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002647 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648}
2649
2650static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2651{
2652 struct audio_device *adev = (struct audio_device *)dev;
2653 struct str_parms *parms;
2654 char *str;
2655 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002656 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07002658 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659
Joe Onorato188b6222016-03-01 11:02:27 -08002660 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002661
2662 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002663
2664 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002665 status = voice_set_parameters(adev, parms);
2666 if (status != 0) {
2667 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002668 }
2669
2670 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
2671 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07002672 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2674 adev->bluetooth_nrec = true;
2675 else
2676 adev->bluetooth_nrec = false;
2677 }
2678
2679 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
2680 if (ret >= 0) {
2681 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2682 adev->screen_off = false;
2683 else
2684 adev->screen_off = true;
2685 }
2686
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002687 ret = str_parms_get_int(parms, "rotation", &val);
2688 if (ret >= 0) {
2689 bool reverse_speakers = false;
2690 switch(val) {
2691 // FIXME: note that the code below assumes that the speakers are in the correct placement
2692 // relative to the user when the device is rotated 90deg from its default rotation. This
2693 // assumption is device-specific, not platform-specific like this code.
2694 case 270:
2695 reverse_speakers = true;
2696 break;
2697 case 0:
2698 case 90:
2699 case 180:
2700 break;
2701 default:
2702 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07002703 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002704 }
Eric Laurent03f09432014-03-25 18:09:11 -07002705 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07002706 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002707 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002708 }
2709
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002710 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
2711 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002712 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002713 }
2714
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08002715 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002716done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002717 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002718 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07002719 ALOGV("%s: exit with code(%d)", __func__, status);
2720 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721}
2722
2723static char* adev_get_parameters(const struct audio_hw_device *dev,
2724 const char *keys)
2725{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002726 struct audio_device *adev = (struct audio_device *)dev;
2727 struct str_parms *reply = str_parms_create();
2728 struct str_parms *query = str_parms_create_str(keys);
2729 char *str;
2730
2731 pthread_mutex_lock(&adev->lock);
2732
2733 voice_get_parameters(adev, query, reply);
2734 str = str_parms_to_str(reply);
2735 str_parms_destroy(query);
2736 str_parms_destroy(reply);
2737
2738 pthread_mutex_unlock(&adev->lock);
2739 ALOGV("%s: exit: returns - %s", __func__, str);
2740 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002741}
2742
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002743static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744{
2745 return 0;
2746}
2747
Haynes Mathew George5191a852013-09-11 14:19:36 -07002748static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
2749{
2750 int ret;
2751 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002752
Eric Laurent4cc4ce12014-09-10 13:21:01 -05002753 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
2754
Haynes Mathew George5191a852013-09-11 14:19:36 -07002755 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002756 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07002757 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002758
Haynes Mathew George5191a852013-09-11 14:19:36 -07002759 return ret;
2760}
2761
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002762static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002763{
2764 return -ENOSYS;
2765}
2766
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002767static int adev_get_master_volume(struct audio_hw_device *dev __unused,
2768 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769{
2770 return -ENOSYS;
2771}
2772
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002773static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002774{
2775 return -ENOSYS;
2776}
2777
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002778static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779{
2780 return -ENOSYS;
2781}
2782
2783static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2784{
2785 struct audio_device *adev = (struct audio_device *)dev;
2786
2787 pthread_mutex_lock(&adev->lock);
2788 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07002789 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07002791 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
2792 voice_is_in_call(adev)) {
2793 voice_stop_call(adev);
2794 adev->current_call_output = NULL;
2795 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 }
2797 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002798
2799 audio_extn_extspk_set_mode(adev->extspk, mode);
2800
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801 return 0;
2802}
2803
2804static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2805{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002806 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002807 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808
Eric Laurent2bafff12016-03-17 12:17:23 -07002809 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002810 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002811 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002812 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00002813 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002814
2815 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816}
2817
2818static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2819{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002820 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002821 return 0;
2822}
2823
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002824static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825 const struct audio_config *config)
2826{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002827 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002829 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
2830 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831}
2832
2833static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002834 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835 audio_devices_t devices,
2836 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002837 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07002838 audio_input_flags_t flags,
2839 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05002840 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841{
2842 struct audio_device *adev = (struct audio_device *)dev;
2843 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002844 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002845 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002846 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847
Eric Laurent994a6932013-07-17 11:51:42 -07002848 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002849 *stream_in = NULL;
2850 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2851 return -EINVAL;
2852
2853 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
2854
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002855 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07002856 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858 in->stream.common.get_sample_rate = in_get_sample_rate;
2859 in->stream.common.set_sample_rate = in_set_sample_rate;
2860 in->stream.common.get_buffer_size = in_get_buffer_size;
2861 in->stream.common.get_channels = in_get_channels;
2862 in->stream.common.get_format = in_get_format;
2863 in->stream.common.set_format = in_set_format;
2864 in->stream.common.standby = in_standby;
2865 in->stream.common.dump = in_dump;
2866 in->stream.common.set_parameters = in_set_parameters;
2867 in->stream.common.get_parameters = in_get_parameters;
2868 in->stream.common.add_audio_effect = in_add_audio_effect;
2869 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2870 in->stream.set_gain = in_set_gain;
2871 in->stream.read = in_read;
2872 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08002873 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874
2875 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002876 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002878 in->standby = 1;
2879 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002880 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002881 in->flags = flags;
Andy Hung6ebe5962016-01-15 17:46:57 -08002882 // in->frames_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883
2884 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002885 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
2886 if (config->sample_rate == 0)
2887 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2888 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2889 config->sample_rate != 8000) {
2890 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2891 ret = -EINVAL;
2892 goto err_open;
2893 }
2894 if (config->format == AUDIO_FORMAT_DEFAULT)
2895 config->format = AUDIO_FORMAT_PCM_16_BIT;
2896 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2897 config->format = AUDIO_FORMAT_PCM_16_BIT;
2898 ret = -EINVAL;
2899 goto err_open;
2900 }
2901
2902 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
2903 in->config = pcm_config_afe_proxy_record;
2904 } else {
2905 in->usecase = USECASE_AUDIO_RECORD;
2906 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
2907 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
2908 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07002909#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002910 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07002911#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08002912 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002913 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002914
Haynes Mathew George03c40102016-01-29 17:57:48 -08002915 in->config = in->realtime ? pcm_config_audio_capture_rt :
2916 pcm_config_audio_capture;
2917
2918 if (!in->realtime) {
2919 frame_size = audio_stream_in_frame_size(&in->stream);
2920 buffer_size = get_input_buffer_size(config->sample_rate,
2921 config->format,
2922 channel_count,
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002923 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08002924 in->config.period_size = buffer_size / frame_size;
2925 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002926 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002927
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002928 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002929 if (in->realtime) {
2930 in->af_period_multiplier = af_period_multiplier;
2931 } else {
2932 in->config.rate = config->sample_rate;
2933 in->af_period_multiplier = 1;
2934 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002935
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002936 /* This stream could be for sound trigger lab,
2937 get sound trigger pcm if present */
2938 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002939
2940 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002941 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002942 return 0;
2943
2944err_open:
2945 free(in);
2946 *stream_in = NULL;
2947 return ret;
2948}
2949
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002950static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951 struct audio_stream_in *stream)
2952{
Eric Laurent994a6932013-07-17 11:51:42 -07002953 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002954
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002955 in_standby(&stream->common);
2956 free(stream);
2957
2958 return;
2959}
2960
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002961static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002962{
2963 return 0;
2964}
2965
Andy Hung31aca912014-03-20 17:14:59 -07002966/* verifies input and output devices and their capabilities.
2967 *
2968 * This verification is required when enabling extended bit-depth or
2969 * sampling rates, as not all qcom products support it.
2970 *
2971 * Suitable for calling only on initialization such as adev_open().
2972 * It fills the audio_device use_case_table[] array.
2973 *
2974 * Has a side-effect that it needs to configure audio routing / devices
2975 * in order to power up the devices and read the device parameters.
2976 * It does not acquire any hw device lock. Should restore the devices
2977 * back to "normal state" upon completion.
2978 */
2979static int adev_verify_devices(struct audio_device *adev)
2980{
2981 /* enumeration is a bit difficult because one really wants to pull
2982 * the use_case, device id, etc from the hidden pcm_device_table[].
2983 * In this case there are the following use cases and device ids.
2984 *
2985 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
2986 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
2987 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
2988 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
2989 * [USECASE_AUDIO_RECORD] = {0, 0},
2990 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
2991 * [USECASE_VOICE_CALL] = {2, 2},
2992 *
2993 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
2994 * USECASE_VOICE_CALL omitted, but possible for either input or output.
2995 */
2996
2997 /* should be the usecases enabled in adev_open_input_stream() */
2998 static const int test_in_usecases[] = {
2999 USECASE_AUDIO_RECORD,
3000 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3001 };
3002 /* should be the usecases enabled in adev_open_output_stream()*/
3003 static const int test_out_usecases[] = {
3004 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3005 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3006 };
3007 static const usecase_type_t usecase_type_by_dir[] = {
3008 PCM_PLAYBACK,
3009 PCM_CAPTURE,
3010 };
3011 static const unsigned flags_by_dir[] = {
3012 PCM_OUT,
3013 PCM_IN,
3014 };
3015
3016 size_t i;
3017 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003018 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003019 char info[512]; /* for possible debug info */
3020
3021 for (dir = 0; dir < 2; ++dir) {
3022 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3023 const unsigned flags_dir = flags_by_dir[dir];
3024 const size_t testsize =
3025 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3026 const int *testcases =
3027 dir ? test_in_usecases : test_out_usecases;
3028 const audio_devices_t audio_device =
3029 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3030
3031 for (i = 0; i < testsize; ++i) {
3032 const audio_usecase_t audio_usecase = testcases[i];
3033 int device_id;
3034 snd_device_t snd_device;
3035 struct pcm_params **pparams;
3036 struct stream_out out;
3037 struct stream_in in;
3038 struct audio_usecase uc_info;
3039 int retval;
3040
3041 pparams = &adev->use_case_table[audio_usecase];
3042 pcm_params_free(*pparams); /* can accept null input */
3043 *pparams = NULL;
3044
3045 /* find the device ID for the use case (signed, for error) */
3046 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3047 if (device_id < 0)
3048 continue;
3049
3050 /* prepare structures for device probing */
3051 memset(&uc_info, 0, sizeof(uc_info));
3052 uc_info.id = audio_usecase;
3053 uc_info.type = usecase_type;
3054 if (dir) {
3055 adev->active_input = &in;
3056 memset(&in, 0, sizeof(in));
3057 in.device = audio_device;
3058 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3059 uc_info.stream.in = &in;
3060 } else {
3061 adev->active_input = NULL;
3062 }
3063 memset(&out, 0, sizeof(out));
3064 out.devices = audio_device; /* only field needed in select_devices */
3065 uc_info.stream.out = &out;
3066 uc_info.devices = audio_device;
3067 uc_info.in_snd_device = SND_DEVICE_NONE;
3068 uc_info.out_snd_device = SND_DEVICE_NONE;
3069 list_add_tail(&adev->usecase_list, &uc_info.list);
3070
3071 /* select device - similar to start_(in/out)put_stream() */
3072 retval = select_devices(adev, audio_usecase);
3073 if (retval >= 0) {
3074 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3075#if LOG_NDEBUG == 0
3076 if (*pparams) {
3077 ALOGV("%s: (%s) card %d device %d", __func__,
3078 dir ? "input" : "output", card_id, device_id);
3079 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003080 } else {
3081 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3082 }
3083#endif
3084 }
3085
3086 /* deselect device - similar to stop_(in/out)put_stream() */
3087 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003088 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003089 /* 2. Disable the rx device */
3090 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003091 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003092 list_remove(&uc_info.list);
3093 }
3094 }
3095 adev->active_input = NULL; /* restore adev state */
3096 return 0;
3097}
3098
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099static int adev_close(hw_device_t *device)
3100{
Andy Hung31aca912014-03-20 17:14:59 -07003101 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003103
3104 if (!adev)
3105 return 0;
3106
3107 pthread_mutex_lock(&adev_init_lock);
3108
3109 if ((--audio_device_ref_count) == 0) {
3110 audio_route_free(adev->audio_route);
3111 free(adev->snd_dev_ref_cnt);
3112 platform_deinit(adev->platform);
3113 audio_extn_extspk_deinit(adev->extspk);
3114 audio_extn_sound_trigger_deinit(adev);
3115 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3116 pcm_params_free(adev->use_case_table[i]);
3117 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003118 if (adev->adm_deinit)
3119 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003120 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003121 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003122
3123 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003125 return 0;
3126}
3127
Glenn Kasten4f993392014-05-14 07:30:48 -07003128/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3129 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3130 * just that it _might_ work.
3131 */
3132static int period_size_is_plausible_for_low_latency(int period_size)
3133{
3134 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003135 case 48:
3136 case 96:
3137 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003138 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003139 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003140 case 240:
3141 case 320:
3142 case 480:
3143 return 1;
3144 default:
3145 return 0;
3146 }
3147}
3148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149static int adev_open(const hw_module_t *module, const char *name,
3150 hw_device_t **device)
3151{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003152 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003153
Eric Laurent2bafff12016-03-17 12:17:23 -07003154 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003155 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003156 pthread_mutex_lock(&adev_init_lock);
3157 if (audio_device_ref_count != 0) {
3158 *device = &adev->device.common;
3159 audio_device_ref_count++;
3160 ALOGV("%s: returning existing instance of adev", __func__);
3161 ALOGV("%s: exit", __func__);
3162 pthread_mutex_unlock(&adev_init_lock);
3163 return 0;
3164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003165 adev = calloc(1, sizeof(struct audio_device));
3166
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003167 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3168
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3170 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3171 adev->device.common.module = (struct hw_module_t *)module;
3172 adev->device.common.close = adev_close;
3173
3174 adev->device.init_check = adev_init_check;
3175 adev->device.set_voice_volume = adev_set_voice_volume;
3176 adev->device.set_master_volume = adev_set_master_volume;
3177 adev->device.get_master_volume = adev_get_master_volume;
3178 adev->device.set_master_mute = adev_set_master_mute;
3179 adev->device.get_master_mute = adev_get_master_mute;
3180 adev->device.set_mode = adev_set_mode;
3181 adev->device.set_mic_mute = adev_set_mic_mute;
3182 adev->device.get_mic_mute = adev_get_mic_mute;
3183 adev->device.set_parameters = adev_set_parameters;
3184 adev->device.get_parameters = adev_get_parameters;
3185 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3186 adev->device.open_output_stream = adev_open_output_stream;
3187 adev->device.close_output_stream = adev_close_output_stream;
3188 adev->device.open_input_stream = adev_open_input_stream;
3189 adev->device.close_input_stream = adev_close_input_stream;
3190 adev->device.dump = adev_dump;
3191
3192 /* Set the default route before the PCM stream is opened */
3193 pthread_mutex_lock(&adev->lock);
3194 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003195 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003196 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003198 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003199 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003200 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003201 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003202 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203 pthread_mutex_unlock(&adev->lock);
3204
3205 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003206 adev->platform = platform_init(adev);
3207 if (!adev->platform) {
3208 free(adev->snd_dev_ref_cnt);
3209 free(adev);
3210 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3211 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003212 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003213 return -EINVAL;
3214 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003215
Eric Laurent0499d4f2014-08-25 22:39:29 -05003216 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003217 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003218
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003219 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3220 if (adev->visualizer_lib == NULL) {
3221 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3222 } else {
3223 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3224 adev->visualizer_start_output =
3225 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3226 "visualizer_hal_start_output");
3227 adev->visualizer_stop_output =
3228 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3229 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003230 }
3231
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003232 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3233 if (adev->offload_effects_lib == NULL) {
3234 ALOGW("%s: DLOPEN failed for %s", __func__,
3235 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3236 } else {
3237 ALOGV("%s: DLOPEN successful for %s", __func__,
3238 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3239 adev->offload_effects_start_output =
3240 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3241 "offload_effects_bundle_hal_start_output");
3242 adev->offload_effects_stop_output =
3243 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3244 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003245 }
3246
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003247 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3248 if (adev->adm_lib == NULL) {
3249 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3250 } else {
3251 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3252 adev->adm_init = (adm_init_t)
3253 dlsym(adev->adm_lib, "adm_init");
3254 adev->adm_deinit = (adm_deinit_t)
3255 dlsym(adev->adm_lib, "adm_deinit");
3256 adev->adm_register_input_stream = (adm_register_input_stream_t)
3257 dlsym(adev->adm_lib, "adm_register_input_stream");
3258 adev->adm_register_output_stream = (adm_register_output_stream_t)
3259 dlsym(adev->adm_lib, "adm_register_output_stream");
3260 adev->adm_deregister_stream = (adm_deregister_stream_t)
3261 dlsym(adev->adm_lib, "adm_deregister_stream");
3262 adev->adm_request_focus = (adm_request_focus_t)
3263 dlsym(adev->adm_lib, "adm_request_focus");
3264 adev->adm_abandon_focus = (adm_abandon_focus_t)
3265 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003266 adev->adm_set_config = (adm_set_config_t)
3267 dlsym(adev->adm_lib, "adm_set_config");
3268 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3269 dlsym(adev->adm_lib, "adm_request_focus_v2");
3270 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3271 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3272 adev->adm_on_routing_change = (adm_on_routing_change_t)
3273 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003274 }
3275
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003276 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003277 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003278
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003280
Andy Hung31aca912014-03-20 17:14:59 -07003281 if (k_enable_extended_precision)
3282 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003283
Glenn Kasten4f993392014-05-14 07:30:48 -07003284 char value[PROPERTY_VALUE_MAX];
3285 int trial;
3286 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3287 trial = atoi(value);
3288 if (period_size_is_plausible_for_low_latency(trial)) {
3289 pcm_config_low_latency.period_size = trial;
3290 pcm_config_low_latency.start_threshold = trial / 4;
3291 pcm_config_low_latency.avail_min = trial / 4;
3292 configured_low_latency_capture_period_size = trial;
3293 }
3294 }
3295 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3296 trial = atoi(value);
3297 if (period_size_is_plausible_for_low_latency(trial)) {
3298 configured_low_latency_capture_period_size = trial;
3299 }
3300 }
3301
vivek mehta1a9b7c02015-06-25 11:49:38 -07003302 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003303
3304 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3305 af_period_multiplier = atoi(value);
3306 if (af_period_multiplier < 0) {
3307 af_period_multiplier = 2;
3308 } else if (af_period_multiplier > 4) {
3309 af_period_multiplier = 4;
3310 }
3311 ALOGV("new period_multiplier = %d", af_period_multiplier);
3312 }
3313
vivek mehta1a9b7c02015-06-25 11:49:38 -07003314 pthread_mutex_unlock(&adev_init_lock);
3315
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003316 if (adev->adm_init)
3317 adev->adm_data = adev->adm_init();
3318
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003319 audio_extn_perf_lock_init();
3320
Eric Laurent2bafff12016-03-17 12:17:23 -07003321 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322 return 0;
3323}
3324
3325static struct hw_module_methods_t hal_module_methods = {
3326 .open = adev_open,
3327};
3328
3329struct audio_module HAL_MODULE_INFO_SYM = {
3330 .common = {
3331 .tag = HARDWARE_MODULE_TAG,
3332 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3333 .hal_api_version = HARDWARE_HAL_API_VERSION,
3334 .id = AUDIO_HARDWARE_MODULE_ID,
3335 .name = "QCOM Audio HAL",
3336 .author = "Code Aurora Forum",
3337 .methods = &hal_module_methods,
3338 },
3339};