blob: bc58d9b45f492dd93cb5dc15f1b604ba9dc83e93 [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
vivek mehta4ed66e62016-04-15 23:33:34 -0700639 platform_check_and_set_capture_backend_cfg(adev, uc_info, snd_device);
640
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700641 /*
642 * This function is to make sure that all the active capture usecases
643 * are always routed to the same input sound device.
644 * For example, if audio-record and voice-call usecases are currently
645 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
646 * is received for voice call then we have to make sure that audio-record
647 * usecase is also switched to earpiece i.e. voice-dmic-ef,
648 * because of the limitation that two devices cannot be enabled
649 * at the same time if they share the same backend.
650 */
651 for (i = 0; i < AUDIO_USECASE_MAX; i++)
652 switch_device[i] = false;
653
654 list_for_each(node, &adev->usecase_list) {
655 usecase = node_to_item(node, struct audio_usecase, list);
656 if (usecase->type != PCM_PLAYBACK &&
657 usecase != uc_info &&
Anish Kumarff864712015-06-03 13:35:11 -0700658 usecase->in_snd_device != snd_device &&
659 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700660 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
661 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700662 platform_get_snd_device_name(usecase->in_snd_device));
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700663 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700664 switch_device[usecase->id] = true;
665 num_uc_to_switch++;
666 }
667 }
668
669 if (num_uc_to_switch) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700670 list_for_each(node, &adev->usecase_list) {
671 usecase = node_to_item(node, struct audio_usecase, list);
672 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700673 disable_snd_device(adev, usecase->in_snd_device);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700674 }
675 }
676
677 list_for_each(node, &adev->usecase_list) {
678 usecase = node_to_item(node, struct audio_usecase, list);
679 if (switch_device[usecase->id]) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700680 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700681 }
682 }
683
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700684 /* Re-route all the usecases on the shared backend other than the
685 specified usecase to new snd devices */
686 list_for_each(node, &adev->usecase_list) {
687 usecase = node_to_item(node, struct audio_usecase, list);
688 /* Update the in_snd_device only before enabling the audio route */
689 if (switch_device[usecase->id] ) {
690 usecase->in_snd_device = snd_device;
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700691 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700692 }
693 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700694 }
695}
696
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800697/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700698static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800699{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700700 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700701 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800702
703 switch (channels) {
704 /*
705 * Do not handle stereo output in Multi-channel cases
706 * Stereo case is handled in normal playback path
707 */
708 case 6:
709 ALOGV("%s: HDMI supports 5.1", __func__);
710 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
711 break;
712 case 8:
713 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
714 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
715 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
716 break;
717 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700718 ALOGE("HDMI does not support multi channel playback");
719 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800720 break;
721 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700722 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800723}
724
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700725static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
726{
727 struct audio_usecase *usecase;
728 struct listnode *node;
729
730 list_for_each(node, &adev->usecase_list) {
731 usecase = node_to_item(node, struct audio_usecase, list);
732 if (usecase->type == VOICE_CALL) {
733 ALOGV("%s: usecase id %d", __func__, usecase->id);
734 return usecase->id;
735 }
736 }
737 return USECASE_INVALID;
738}
739
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800740struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
741 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700742{
743 struct audio_usecase *usecase;
744 struct listnode *node;
745
746 list_for_each(node, &adev->usecase_list) {
747 usecase = node_to_item(node, struct audio_usecase, list);
748 if (usecase->id == uc_id)
749 return usecase;
750 }
751 return NULL;
752}
753
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800754int select_devices(struct audio_device *adev,
755 audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800756{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800757 snd_device_t out_snd_device = SND_DEVICE_NONE;
758 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700759 struct audio_usecase *usecase = NULL;
760 struct audio_usecase *vc_usecase = NULL;
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800761 struct audio_usecase *hfp_usecase = NULL;
762 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800763 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700764 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800765
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700766 usecase = get_usecase_from_list(adev, uc_id);
767 if (usecase == NULL) {
768 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
769 return -EINVAL;
770 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800771
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800772 if ((usecase->type == VOICE_CALL) ||
773 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700774 out_snd_device = platform_get_output_snd_device(adev->platform,
775 usecase->stream.out->devices);
776 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700777 usecase->devices = usecase->stream.out->devices;
778 } else {
779 /*
780 * If the voice call is active, use the sound devices of voice call usecase
781 * so that it would not result any device switch. All the usecases will
782 * be switched to new device when select_devices() is called for voice call
783 * usecase. This is to avoid switching devices for voice call when
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700784 * check_and_route_playback_usecases() is called below.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700785 */
Vineeta Srivastava4b89e372014-06-19 14:21:42 -0700786 if (voice_is_in_call(adev)) {
Ravi Kumar Alamandaa237ecc2014-07-24 17:27:05 -0700787 vc_usecase = get_usecase_from_list(adev,
788 get_voice_usecase_id_from_list(adev));
789 if ((vc_usecase != NULL) &&
790 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
791 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700792 in_snd_device = vc_usecase->in_snd_device;
793 out_snd_device = vc_usecase->out_snd_device;
794 }
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -0800795 } else if (audio_extn_hfp_is_active(adev)) {
796 hfp_ucid = audio_extn_hfp_get_usecase();
797 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
798 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
799 in_snd_device = hfp_usecase->in_snd_device;
800 out_snd_device = hfp_usecase->out_snd_device;
801 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700802 }
803 if (usecase->type == PCM_PLAYBACK) {
804 usecase->devices = usecase->stream.out->devices;
805 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700806 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700807 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700808 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700809 if (usecase->stream.out == adev->primary_output &&
810 adev->active_input &&
Eric Laurent50a38ed2015-10-14 18:48:06 -0700811 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
812 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800813 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700814 select_devices(adev, adev->active_input->usecase);
815 }
816 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700817 } else if (usecase->type == PCM_CAPTURE) {
818 usecase->devices = usecase->stream.in->device;
819 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700820 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700821 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent50a38ed2015-10-14 18:48:06 -0700822 if (adev->active_input &&
823 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
824 adev->mode == AUDIO_MODE_IN_COMMUNICATION)) {
Ravi Kumar Alamandaf2829012014-11-12 16:16:10 -0800825 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda04643592015-09-24 19:17:26 -0700826 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
827 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
828 } else if (adev->primary_output) {
829 out_device = adev->primary_output->devices;
830 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700831 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -0700832 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700833 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700834 }
835 }
836
837 if (out_snd_device == usecase->out_snd_device &&
838 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800839 return 0;
840 }
841
Eric Laurent2bafff12016-03-17 12:17:23 -0700842 if (out_snd_device != SND_DEVICE_NONE &&
843 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
844 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
845 __func__,
846 use_case_table[uc_id],
847 adev->last_logged_snd_device[uc_id][0],
848 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
849 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
850 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
851 -1,
852 out_snd_device,
853 platform_get_snd_device_name(out_snd_device),
854 platform_get_snd_device_acdb_id(out_snd_device));
855 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
856 }
857 if (in_snd_device != SND_DEVICE_NONE &&
858 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
859 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
860 __func__,
861 use_case_table[uc_id],
862 adev->last_logged_snd_device[uc_id][1],
863 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
864 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
865 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
866 -1,
867 in_snd_device,
868 platform_get_snd_device_name(in_snd_device),
869 platform_get_snd_device_acdb_id(in_snd_device));
870 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
871 }
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800872
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800873 /*
874 * Limitation: While in call, to do a device switch we need to disable
875 * and enable both RX and TX devices though one of them is same as current
876 * device.
877 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700878 if ((usecase->type == VOICE_CALL) &&
879 (usecase->in_snd_device != SND_DEVICE_NONE) &&
880 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700881 status = platform_switch_voice_call_device_pre(adev->platform);
vivek mehta765eb642015-08-07 19:46:06 -0700882 /* Disable sidetone only if voice call already exists */
883 if (voice_is_call_state_active(adev))
884 voice_set_sidetone(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800885 }
886
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 /* Disable current sound devices */
888 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700889 disable_audio_route(adev, usecase);
890 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800891 }
892
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700894 disable_audio_route(adev, usecase);
895 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800896 }
897
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700898 /* Applicable only on the targets that has external modem.
899 * New device information should be sent to modem before enabling
900 * the devices to reduce in-call device switch time.
901 */
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700902 if ((usecase->type == VOICE_CALL) &&
903 (usecase->in_snd_device != SND_DEVICE_NONE) &&
904 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700905 status = platform_switch_voice_call_enable_device_config(adev->platform,
906 out_snd_device,
907 in_snd_device);
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -0700908 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700909
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700910 /* Enable new sound devices */
911 if (out_snd_device != SND_DEVICE_NONE) {
912 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -0700913 check_and_route_playback_usecases(adev, usecase, out_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700914 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800915 }
916
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700917 if (in_snd_device != SND_DEVICE_NONE) {
918 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700919 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700920 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700921
Eric Laurentb23d5282013-05-14 15:27:20 -0700922 if (usecase->type == VOICE_CALL)
923 status = platform_switch_voice_call_device_post(adev->platform,
924 out_snd_device,
925 in_snd_device);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800926
sangwoo170731f2013-06-08 15:36:36 +0900927 usecase->in_snd_device = in_snd_device;
928 usecase->out_snd_device = out_snd_device;
929
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700930 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900931
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700932 /* Applicable only on the targets that has external modem.
933 * Enable device command should be sent to modem only after
934 * enabling voice call mixer controls
935 */
vivek mehta765eb642015-08-07 19:46:06 -0700936 if (usecase->type == VOICE_CALL) {
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700937 status = platform_switch_voice_call_usecase_route_post(adev->platform,
938 out_snd_device,
939 in_snd_device);
vivek mehta765eb642015-08-07 19:46:06 -0700940 /* Enable sidetone only if voice call already exists */
941 if (voice_is_call_state_active(adev))
942 voice_set_sidetone(adev, out_snd_device, true);
943 }
Ravi Kumar Alamanda83281a92014-05-19 18:14:57 -0700944
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800945 return status;
946}
947
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948static int stop_input_stream(struct stream_in *in)
949{
950 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800951 struct audio_usecase *uc_info;
952 struct audio_device *adev = in->dev;
953
Eric Laurentc8400632013-02-14 19:04:54 -0800954 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800955
Eric Laurent994a6932013-07-17 11:51:42 -0700956 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700957 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800958 uc_info = get_usecase_from_list(adev, in->usecase);
959 if (uc_info == NULL) {
960 ALOGE("%s: Could not find the usecase (%d) in the list",
961 __func__, in->usecase);
962 return -EINVAL;
963 }
964
Eric Laurent150dbfe2013-02-27 14:31:02 -0800965 /* 1. Disable stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700966 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700967
968 /* 2. Disable the tx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -0700969 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800970
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800971 list_remove(&uc_info->list);
972 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973
Eric Laurent994a6932013-07-17 11:51:42 -0700974 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800975 return ret;
976}
977
978int start_input_stream(struct stream_in *in)
979{
980 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -0800981 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800982 struct audio_usecase *uc_info;
983 struct audio_device *adev = in->dev;
984
Eric Laurent994a6932013-07-17 11:51:42 -0700985 ALOGV("%s: enter: usecase(%d)", __func__, in->usecase);
Eric Laurentb23d5282013-05-14 15:27:20 -0700986 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800987 if (in->pcm_device_id < 0) {
988 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
989 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -0800990 ret = -EINVAL;
991 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800992 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700993
994 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
996 uc_info->id = in->usecase;
997 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800998 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999 uc_info->devices = in->device;
1000 uc_info->in_snd_device = SND_DEVICE_NONE;
1001 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001002
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001003 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001004
1005 audio_extn_perf_lock_acquire();
1006
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001007 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001008
Eric Laurentc8400632013-02-14 19:04:54 -08001009 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001010 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001011
Andy Hung6ebe5962016-01-15 17:46:57 -08001012 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001013 unsigned int pcm_open_retry_count = 0;
1014
1015 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1016 flags |= PCM_MMAP | PCM_NOIRQ;
1017 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001018 } else if (in->realtime) {
1019 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001021
1022 while (1) {
1023 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1024 flags, &in->config);
1025 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1026 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1027 if (in->pcm != NULL) {
1028 pcm_close(in->pcm);
1029 in->pcm = NULL;
1030 }
1031 if (pcm_open_retry_count-- == 0) {
1032 ret = -EIO;
1033 goto error_open;
1034 }
1035 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1036 continue;
1037 }
1038 break;
1039 }
1040
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001041 ALOGV("%s: pcm_prepare", __func__);
1042 ret = pcm_prepare(in->pcm);
1043 if (ret < 0) {
1044 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1045 pcm_close(in->pcm);
1046 in->pcm = NULL;
1047 goto error_open;
1048 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001049 register_in_stream(in);
1050 if (in->realtime) {
1051 ret = pcm_start(in->pcm);
1052 }
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001053 audio_extn_perf_lock_release();
1054
Eric Laurent994a6932013-07-17 11:51:42 -07001055 ALOGV("%s: exit", __func__);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001056
Eric Laurentc8400632013-02-14 19:04:54 -08001057 return ret;
1058
1059error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060 stop_input_stream(in);
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001061 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001062
1063error_config:
1064 adev->active_input = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07001065 ALOGW("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001066
1067 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068}
1069
Eric Laurenta1478072015-09-21 17:21:52 -07001070void lock_input_stream(struct stream_in *in)
1071{
1072 pthread_mutex_lock(&in->pre_lock);
1073 pthread_mutex_lock(&in->lock);
1074 pthread_mutex_unlock(&in->pre_lock);
1075}
1076
1077void lock_output_stream(struct stream_out *out)
1078{
1079 pthread_mutex_lock(&out->pre_lock);
1080 pthread_mutex_lock(&out->lock);
1081 pthread_mutex_unlock(&out->pre_lock);
1082}
1083
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001084/* must be called with out->lock locked */
1085static int send_offload_cmd_l(struct stream_out* out, int command)
1086{
1087 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1088
1089 ALOGVV("%s %d", __func__, command);
1090
1091 cmd->cmd = command;
1092 list_add_tail(&out->offload_cmd_list, &cmd->node);
1093 pthread_cond_signal(&out->offload_cond);
1094 return 0;
1095}
1096
1097/* must be called iwth out->lock locked */
1098static void stop_compressed_output_l(struct stream_out *out)
1099{
1100 out->offload_state = OFFLOAD_STATE_IDLE;
1101 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001102 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001103 if (out->compr != NULL) {
1104 compress_stop(out->compr);
1105 while (out->offload_thread_blocked) {
1106 pthread_cond_wait(&out->cond, &out->lock);
1107 }
1108 }
1109}
1110
1111static void *offload_thread_loop(void *context)
1112{
1113 struct stream_out *out = (struct stream_out *) context;
1114 struct listnode *item;
1115
1116 out->offload_state = OFFLOAD_STATE_IDLE;
1117 out->playback_started = 0;
1118
1119 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1120 set_sched_policy(0, SP_FOREGROUND);
1121 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1122
1123 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07001124 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001125 for (;;) {
1126 struct offload_cmd *cmd = NULL;
1127 stream_callback_event_t event;
1128 bool send_callback = false;
1129
1130 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1131 __func__, list_empty(&out->offload_cmd_list),
1132 out->offload_state);
1133 if (list_empty(&out->offload_cmd_list)) {
1134 ALOGV("%s SLEEPING", __func__);
1135 pthread_cond_wait(&out->offload_cond, &out->lock);
1136 ALOGV("%s RUNNING", __func__);
1137 continue;
1138 }
1139
1140 item = list_head(&out->offload_cmd_list);
1141 cmd = node_to_item(item, struct offload_cmd, node);
1142 list_remove(item);
1143
1144 ALOGVV("%s STATE %d CMD %d out->compr %p",
1145 __func__, out->offload_state, cmd->cmd, out->compr);
1146
1147 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1148 free(cmd);
1149 break;
1150 }
1151
1152 if (out->compr == NULL) {
1153 ALOGE("%s: Compress handle is NULL", __func__);
Andy Hung68f55fd2016-04-21 11:51:11 -07001154 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001155 pthread_cond_signal(&out->cond);
1156 continue;
1157 }
1158 out->offload_thread_blocked = true;
1159 pthread_mutex_unlock(&out->lock);
1160 send_callback = false;
1161 switch(cmd->cmd) {
1162 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
1163 compress_wait(out->compr, -1);
1164 send_callback = true;
1165 event = STREAM_CBK_EVENT_WRITE_READY;
1166 break;
1167 case OFFLOAD_CMD_PARTIAL_DRAIN:
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001168 compress_next_track(out->compr);
1169 compress_partial_drain(out->compr);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001170 send_callback = true;
1171 event = STREAM_CBK_EVENT_DRAIN_READY;
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001172 /* Resend the metadata for next iteration */
1173 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001174 break;
1175 case OFFLOAD_CMD_DRAIN:
1176 compress_drain(out->compr);
1177 send_callback = true;
1178 event = STREAM_CBK_EVENT_DRAIN_READY;
1179 break;
1180 default:
1181 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1182 break;
1183 }
Eric Laurenta1478072015-09-21 17:21:52 -07001184 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001185 out->offload_thread_blocked = false;
1186 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001187 if (send_callback) {
Ravi Kumar Alamandacc4f6bf2014-12-02 19:21:51 -08001188 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001189 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001190 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001191 free(cmd);
1192 }
1193
1194 pthread_cond_signal(&out->cond);
1195 while (!list_empty(&out->offload_cmd_list)) {
1196 item = list_head(&out->offload_cmd_list);
1197 list_remove(item);
1198 free(node_to_item(item, struct offload_cmd, node));
1199 }
1200 pthread_mutex_unlock(&out->lock);
1201
1202 return NULL;
1203}
1204
1205static int create_offload_callback_thread(struct stream_out *out)
1206{
1207 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1208 list_init(&out->offload_cmd_list);
1209 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1210 offload_thread_loop, out);
1211 return 0;
1212}
1213
1214static int destroy_offload_callback_thread(struct stream_out *out)
1215{
Eric Laurenta1478072015-09-21 17:21:52 -07001216 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001217 stop_compressed_output_l(out);
1218 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1219
1220 pthread_mutex_unlock(&out->lock);
1221 pthread_join(out->offload_thread, (void **) NULL);
1222 pthread_cond_destroy(&out->offload_cond);
1223
1224 return 0;
1225}
1226
Eric Laurent07eeafd2013-10-06 12:52:49 -07001227static bool allow_hdmi_channel_config(struct audio_device *adev)
1228{
1229 struct listnode *node;
1230 struct audio_usecase *usecase;
1231 bool ret = true;
1232
1233 list_for_each(node, &adev->usecase_list) {
1234 usecase = node_to_item(node, struct audio_usecase, list);
1235 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1236 /*
1237 * If voice call is already existing, do not proceed further to avoid
1238 * disabling/enabling both RX and TX devices, CSD calls, etc.
1239 * Once the voice call done, the HDMI channels can be configured to
1240 * max channels of remaining use cases.
1241 */
1242 if (usecase->id == USECASE_VOICE_CALL) {
Joe Onorato188b6222016-03-01 11:02:27 -08001243 ALOGV("%s: voice call is active, no change in HDMI channels",
Eric Laurent07eeafd2013-10-06 12:52:49 -07001244 __func__);
1245 ret = false;
1246 break;
1247 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
Joe Onorato188b6222016-03-01 11:02:27 -08001248 ALOGV("%s: multi channel playback is active, "
Eric Laurent07eeafd2013-10-06 12:52:49 -07001249 "no change in HDMI channels", __func__);
1250 ret = false;
1251 break;
1252 }
1253 }
1254 }
1255 return ret;
1256}
1257
1258static int check_and_set_hdmi_channels(struct audio_device *adev,
1259 unsigned int channels)
1260{
1261 struct listnode *node;
1262 struct audio_usecase *usecase;
1263
1264 /* Check if change in HDMI channel config is allowed */
1265 if (!allow_hdmi_channel_config(adev))
1266 return 0;
1267
1268 if (channels == adev->cur_hdmi_channels) {
Joe Onorato188b6222016-03-01 11:02:27 -08001269 ALOGV("%s: Requested channels are same as current", __func__);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001270 return 0;
1271 }
1272
1273 platform_set_hdmi_channels(adev->platform, channels);
1274 adev->cur_hdmi_channels = channels;
1275
1276 /*
1277 * Deroute all the playback streams routed to HDMI so that
1278 * the back end is deactivated. Note that backend will not
1279 * be deactivated if any one stream is connected to it.
1280 */
1281 list_for_each(node, &adev->usecase_list) {
1282 usecase = node_to_item(node, struct audio_usecase, list);
1283 if (usecase->type == PCM_PLAYBACK &&
1284 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001285 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001286 }
1287 }
1288
1289 /*
1290 * Enable all the streams disabled above. Now the HDMI backend
1291 * will be activated with new channel configuration
1292 */
1293 list_for_each(node, &adev->usecase_list) {
1294 usecase = node_to_item(node, struct audio_usecase, list);
1295 if (usecase->type == PCM_PLAYBACK &&
1296 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001297 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001298 }
1299 }
1300
1301 return 0;
1302}
1303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001304static int stop_output_stream(struct stream_out *out)
1305{
1306 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001307 struct audio_usecase *uc_info;
1308 struct audio_device *adev = out->dev;
1309
Eric Laurent994a6932013-07-17 11:51:42 -07001310 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001311 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001312 uc_info = get_usecase_from_list(adev, out->usecase);
1313 if (uc_info == NULL) {
1314 ALOGE("%s: Could not find the usecase (%d) in the list",
1315 __func__, out->usecase);
1316 return -EINVAL;
1317 }
1318
Haynes Mathew George41f86652014-06-17 14:22:15 -07001319 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1320 if (adev->visualizer_stop_output != NULL)
1321 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1322 if (adev->offload_effects_stop_output != NULL)
1323 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1324 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001325
Eric Laurent150dbfe2013-02-27 14:31:02 -08001326 /* 1. Get and set stream specific mixer controls */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001327 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001328
1329 /* 2. Disable the rx device */
Ravi Kumar Alamandac38e4522014-04-14 11:46:35 -07001330 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001331
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001332 list_remove(&uc_info->list);
1333 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001334
Eric Laurent0499d4f2014-08-25 22:39:29 -05001335 audio_extn_extspk_update(adev->extspk);
1336
Eric Laurent07eeafd2013-10-06 12:52:49 -07001337 /* Must be called after removing the usecase from list */
1338 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1339 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1340
Eric Laurent994a6932013-07-17 11:51:42 -07001341 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001342 return ret;
1343}
1344
1345int start_output_stream(struct stream_out *out)
1346{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001347 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348 struct audio_usecase *uc_info;
1349 struct audio_device *adev = out->dev;
1350
Eric Laurent994a6932013-07-17 11:51:42 -07001351 ALOGV("%s: enter: usecase(%d: %s) devices(%#x)",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001352 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001353 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001354 if (out->pcm_device_id < 0) {
1355 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1356 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001357 ret = -EINVAL;
1358 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001359 }
1360
1361 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
1362 uc_info->id = out->usecase;
1363 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001364 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001365 uc_info->devices = out->devices;
1366 uc_info->in_snd_device = SND_DEVICE_NONE;
1367 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001368
Eric Laurent07eeafd2013-10-06 12:52:49 -07001369 /* This must be called before adding this usecase to the list */
1370 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1371 check_and_set_hdmi_channels(adev, out->config.channels);
1372
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001373 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001374
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001375 audio_extn_perf_lock_acquire();
1376
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001377 select_devices(adev, out->usecase);
1378
Eric Laurent0499d4f2014-08-25 22:39:29 -05001379 audio_extn_extspk_update(adev->extspk);
1380
Andy Hung31aca912014-03-20 17:14:59 -07001381 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001382 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001383 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001384 unsigned int flags = PCM_OUT;
1385 unsigned int pcm_open_retry_count = 0;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001386
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001387 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1388 flags |= PCM_MMAP | PCM_NOIRQ;
1389 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001390 } else if (out->realtime) {
1391 flags |= PCM_MMAP | PCM_NOIRQ;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001392 } else
1393 flags |= PCM_MONOTONIC;
1394
1395 while (1) {
1396 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1397 flags, &out->config);
1398 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
1399 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1400 if (out->pcm != NULL) {
1401 pcm_close(out->pcm);
1402 out->pcm = NULL;
1403 }
1404 if (pcm_open_retry_count-- == 0) {
1405 ret = -EIO;
1406 goto error_open;
1407 }
1408 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1409 continue;
1410 }
1411 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001412 }
Ravi Kumar Alamanda50919a72015-10-02 09:37:33 -07001413 ALOGV("%s: pcm_prepare", __func__);
1414 if (pcm_is_ready(out->pcm)) {
1415 ret = pcm_prepare(out->pcm);
1416 if (ret < 0) {
1417 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
1418 pcm_close(out->pcm);
1419 out->pcm = NULL;
1420 goto error_open;
1421 }
1422 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001423 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001424 out->pcm = NULL;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07001425 out->compr = compress_open(adev->snd_card, out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001426 COMPRESS_IN, &out->compr_config);
1427 if (out->compr && !is_compress_ready(out->compr)) {
1428 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1429 compress_close(out->compr);
1430 out->compr = NULL;
1431 ret = -EIO;
1432 goto error_open;
1433 }
1434 if (out->offload_callback)
1435 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001436
1437 if (adev->visualizer_start_output != NULL)
Haynes Mathew George41f86652014-06-17 14:22:15 -07001438 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1439 if (adev->offload_effects_start_output != NULL)
1440 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001441 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001442 ret = 0;
1443 register_out_stream(out);
1444 if (out->realtime) {
1445 ret = pcm_start(out->pcm);
1446 }
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001447 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001448 ALOGV("%s: exit", __func__);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001449 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001450error_open:
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07001451 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001452 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001453error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001454 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001455}
1456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457static int check_input_parameters(uint32_t sample_rate,
1458 audio_format_t format,
1459 int channel_count)
1460{
vivek mehta4ed66e62016-04-15 23:33:34 -07001461 if ((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT)) {
vivek mehtadae44712015-07-27 14:13:18 -07001462 ALOGE("%s: unsupported AUDIO FORMAT (%d) ", __func__, format);
1463 return -EINVAL;
1464 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465
vivek mehtadae44712015-07-27 14:13:18 -07001466 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > MAX_CHANNEL_COUNT)) {
Jean-Michel Trivic0750692015-10-12 12:12:32 -07001467 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
vivek mehtadae44712015-07-27 14:13:18 -07001468 channel_count, MIN_CHANNEL_COUNT, MAX_CHANNEL_COUNT);
1469 return -EINVAL;
1470 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001471
1472 switch (sample_rate) {
1473 case 8000:
1474 case 11025:
1475 case 12000:
1476 case 16000:
1477 case 22050:
1478 case 24000:
1479 case 32000:
1480 case 44100:
1481 case 48000:
1482 break;
1483 default:
vivek mehtadae44712015-07-27 14:13:18 -07001484 ALOGE("%s: unsupported (%d) samplerate passed ", __func__, sample_rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485 return -EINVAL;
1486 }
1487
1488 return 0;
1489}
1490
1491static size_t get_input_buffer_size(uint32_t sample_rate,
1492 audio_format_t format,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001493 int channel_count,
1494 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495{
1496 size_t size = 0;
1497
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001498 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1499 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001501 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Glenn Kasten68e79ce2014-07-15 10:56:59 -07001502 if (is_low_latency)
Glenn Kasten4f993392014-05-14 07:30:48 -07001503 size = configured_low_latency_capture_period_size;
vivek mehta4ed66e62016-04-15 23:33:34 -07001504
1505 size *= channel_count * audio_bytes_per_sample(format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506
Glenn Kasten4f993392014-05-14 07:30:48 -07001507 /* make sure the size is multiple of 32 bytes
1508 * At 48 kHz mono 16-bit PCM:
1509 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1510 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1511 */
1512 size += 0x1f;
1513 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001514
1515 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001516}
1517
1518static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1519{
1520 struct stream_out *out = (struct stream_out *)stream;
1521
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001522 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523}
1524
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001525static int out_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001526{
1527 return -ENOSYS;
1528}
1529
1530static size_t out_get_buffer_size(const struct audio_stream *stream)
1531{
1532 struct stream_out *out = (struct stream_out *)stream;
1533
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001534 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1535 return out->compr_config.fragment_size;
1536 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08001537 return out->config.period_size * out->af_period_multiplier *
Eric Laurentfdf296a2014-07-03 16:41:51 -07001538 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539}
1540
1541static uint32_t out_get_channels(const struct audio_stream *stream)
1542{
1543 struct stream_out *out = (struct stream_out *)stream;
1544
1545 return out->channel_mask;
1546}
1547
1548static audio_format_t out_get_format(const struct audio_stream *stream)
1549{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001550 struct stream_out *out = (struct stream_out *)stream;
1551
1552 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001553}
1554
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001555static int out_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556{
1557 return -ENOSYS;
1558}
1559
1560static int out_standby(struct audio_stream *stream)
1561{
1562 struct stream_out *out = (struct stream_out *)stream;
1563 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001564
Eric Laurent994a6932013-07-17 11:51:42 -07001565 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001566 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567
Eric Laurenta1478072015-09-21 17:21:52 -07001568 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001569 if (!out->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001570 if (adev->adm_deregister_stream)
1571 adev->adm_deregister_stream(adev->adm_data, out->handle);
1572
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001573 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001574 out->standby = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001575 if (out->usecase != USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1576 if (out->pcm) {
1577 pcm_close(out->pcm);
1578 out->pcm = NULL;
1579 }
1580 } else {
1581 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001582 out->gapless_mdata.encoder_delay = 0;
1583 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001584 if (out->compr != NULL) {
1585 compress_close(out->compr);
1586 out->compr = NULL;
1587 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001588 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001589 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001590 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591 }
1592 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001593 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001594 return 0;
1595}
1596
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001597static int out_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598{
1599 return 0;
1600}
1601
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001602static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1603{
1604 int ret = 0;
1605 char value[32];
1606 struct compr_gapless_mdata tmp_mdata;
1607
1608 if (!out || !parms) {
1609 return -EINVAL;
1610 }
1611
1612 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1613 if (ret >= 0) {
1614 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
1615 } else {
1616 return -EINVAL;
1617 }
1618
1619 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1620 if (ret >= 0) {
1621 tmp_mdata.encoder_padding = atoi(value);
1622 } else {
1623 return -EINVAL;
1624 }
1625
1626 out->gapless_mdata = tmp_mdata;
1627 out->send_new_metadata = 1;
1628 ALOGV("%s new encoder delay %u and padding %u", __func__,
1629 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1630
1631 return 0;
1632}
1633
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001634static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1635{
1636 return out == adev->primary_output || out == adev->voice_tx_output;
1637}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001638
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001639static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1640{
1641 struct stream_out *out = (struct stream_out *)stream;
1642 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001643 struct audio_usecase *usecase;
1644 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001645 struct str_parms *parms;
1646 char value[32];
1647 int ret, val = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001648 bool select_new_device = false;
Eric Laurent03f09432014-03-25 18:09:11 -07001649 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650
Joe Onorato188b6222016-03-01 11:02:27 -08001651 ALOGV("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 parms = str_parms_create_str(kvpairs);
1654 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1655 if (ret >= 0) {
1656 val = atoi(value);
Eric Laurenta1478072015-09-21 17:21:52 -07001657 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001658 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001660 /*
1661 * When HDMI cable is unplugged the music playback is paused and
1662 * the policy manager sends routing=0. But the audioflinger
1663 * continues to write data until standby time (3sec).
1664 * As the HDMI core is turned off, the write gets blocked.
1665 * Avoid this by routing audio to speaker until standby.
1666 */
1667 if (out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL &&
1668 val == AUDIO_DEVICE_NONE) {
1669 val = AUDIO_DEVICE_OUT_SPEAKER;
1670 }
1671
1672 /*
1673 * select_devices() call below switches all the usecases on the same
Ravi Kumar Alamandab7ea4f52015-06-08 16:44:05 -07001674 * backend to the new device. Refer to check_and_route_playback_usecases() in
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001675 * the select_devices(). But how do we undo this?
1676 *
1677 * For example, music playback is active on headset (deep-buffer usecase)
1678 * and if we go to ringtones and select a ringtone, low-latency usecase
1679 * will be started on headset+speaker. As we can't enable headset+speaker
1680 * and headset devices at the same time, select_devices() switches the music
1681 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1682 * So when the ringtone playback is completed, how do we undo the same?
1683 *
1684 * We are relying on the out_set_parameters() call on deep-buffer output,
1685 * once the ringtone playback is ended.
1686 * NOTE: We should not check if the current devices are same as new devices.
1687 * Because select_devices() must be called to switch back the music
1688 * playback to headset.
1689 */
Haynes Mathew George03c40102016-01-29 17:57:48 -08001690 audio_devices_t new_dev = val;
1691 if (new_dev != AUDIO_DEVICE_NONE) {
1692 bool same_dev = out->devices == new_dev;
1693 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001694
Haynes Mathew George03c40102016-01-29 17:57:48 -08001695 if (!out->standby) {
1696 if (!same_dev) {
1697 ALOGV("update routing change");
1698 out->routing_change = true;
1699 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001700 select_devices(adev, out->usecase);
Haynes Mathew George03c40102016-01-29 17:57:48 -08001701 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001702
Eric Laurenta7657192014-10-09 21:09:33 -07001703 if (output_drives_call(adev, out)) {
1704 if (!voice_is_in_call(adev)) {
1705 if (adev->mode == AUDIO_MODE_IN_CALL) {
1706 adev->current_call_output = out;
1707 ret = voice_start_call(adev);
1708 }
1709 } else {
1710 adev->current_call_output = out;
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001711 voice_update_devices_for_all_voice_usecases(adev);
Eric Laurenta7657192014-10-09 21:09:33 -07001712 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001713 }
1714 }
1715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001716 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001717 pthread_mutex_unlock(&out->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05001718
1719 /*handles device and call state changes*/
1720 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001722
1723 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1724 parse_compress_metadata(out, parms);
1725 }
1726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07001728 ALOGV("%s: exit: code(%d)", __func__, status);
1729 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730}
1731
1732static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1733{
1734 struct stream_out *out = (struct stream_out *)stream;
1735 struct str_parms *query = str_parms_create_str(keys);
1736 char *str;
1737 char value[256];
1738 struct str_parms *reply = str_parms_create();
1739 size_t i, j;
1740 int ret;
1741 bool first = true;
Eric Laurent994a6932013-07-17 11:51:42 -07001742 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1744 if (ret >= 0) {
1745 value[0] = '\0';
1746 i = 0;
1747 while (out->supported_channel_masks[i] != 0) {
1748 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1749 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1750 if (!first) {
1751 strcat(value, "|");
1752 }
1753 strcat(value, out_channels_name_to_enum_table[j].name);
1754 first = false;
1755 break;
1756 }
1757 }
1758 i++;
1759 }
1760 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
1761 str = str_parms_to_str(reply);
1762 } else {
1763 str = strdup(keys);
1764 }
1765 str_parms_destroy(query);
1766 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07001767 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 return str;
1769}
1770
1771static uint32_t out_get_latency(const struct audio_stream_out *stream)
1772{
Haynes Mathew George03c40102016-01-29 17:57:48 -08001773 uint32_t hw_delay, period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774 struct stream_out *out = (struct stream_out *)stream;
1775
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001776 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD)
1777 return COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Haynes Mathew George03c40102016-01-29 17:57:48 -08001778 else if (out->realtime) {
1779 // since the buffer won't be filled up faster than realtime,
1780 // return a smaller number
1781 period_ms = (out->af_period_multiplier * out->config.period_size *
1782 1000) / (out->config.rate);
1783 hw_delay = platform_render_latency(out->usecase)/1000;
1784 return period_ms + hw_delay;
1785 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001786
1787 return (out->config.period_count * out->config.period_size * 1000) /
1788 (out->config.rate);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789}
1790
1791static int out_set_volume(struct audio_stream_out *stream, float left,
1792 float right)
1793{
Eric Laurenta9024de2013-04-04 09:19:12 -07001794 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001795 int volume[2];
1796
Eric Laurenta9024de2013-04-04 09:19:12 -07001797 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1798 /* only take left channel into account: the API is for stereo anyway */
1799 out->muted = (left == 0.0f);
1800 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001801 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1802 const char *mixer_ctl_name = "Compress Playback Volume";
1803 struct audio_device *adev = out->dev;
1804 struct mixer_ctl *ctl;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001805 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1806 if (!ctl) {
Haynes Mathew George20bcfa82014-06-25 13:37:03 -07001807 /* try with the control based on device id */
1808 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
1809 PCM_PLAYBACK);
1810 char ctl_name[128] = {0};
1811 snprintf(ctl_name, sizeof(ctl_name),
1812 "Compress Playback %d Volume", pcm_device_id);
1813 ctl = mixer_get_ctl_by_name(adev->mixer, ctl_name);
1814 if (!ctl) {
1815 ALOGE("%s: Could not get volume ctl mixer cmd", __func__);
1816 return -EINVAL;
1817 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001818 }
1819 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
1820 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
1821 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
1822 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07001823 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001825 return -ENOSYS;
1826}
1827
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001828#ifdef NO_AUDIO_OUT
1829static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
1830 const void *buffer, size_t bytes)
1831{
1832 struct stream_out *out = (struct stream_out *)stream;
1833
1834 /* No Output device supported other than BT for playback.
1835 * Sleep for the amount of buffer duration
1836 */
Eric Laurenta1478072015-09-21 17:21:52 -07001837 lock_output_stream(out);
Uday Kishore Pasupuletib14d76b2015-11-13 20:06:37 -08001838 usleep(bytes * 1000000 / audio_stream_out_frame_size(&out->stream.common) /
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07001839 out_get_sample_rate(&out->stream.common));
1840 pthread_mutex_unlock(&out->lock);
1841 return bytes;
1842}
1843#endif
1844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
1846 size_t bytes)
1847{
1848 struct stream_out *out = (struct stream_out *)stream;
1849 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07001850 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851
Eric Laurenta1478072015-09-21 17:21:52 -07001852 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001854 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08001855 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001856 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001857 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001858 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001859 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07001860 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 goto exit;
1862 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001864
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001865 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001866 ALOGVV("%s: writing buffer (%d bytes) to compress device", __func__, bytes);
1867 if (out->send_new_metadata) {
1868 ALOGVV("send new gapless metadata");
1869 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
1870 out->send_new_metadata = 0;
1871 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08001872 unsigned int avail;
1873 struct timespec tstamp;
1874 ret = compress_get_hpointer(out->compr, &avail, &tstamp);
1875 /* Do not limit write size if the available frames count is unknown */
1876 if (ret != 0) {
1877 avail = bytes;
1878 }
1879 if (avail == 0) {
1880 ret = 0;
1881 } else {
1882 if (avail > bytes) {
1883 avail = bytes;
1884 }
1885 ret = compress_write(out->compr, buffer, avail);
1886 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %zd",
1887 __func__, avail, ret);
1888 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001889
Eric Laurent6e895242013-09-05 16:10:57 -07001890 if (ret >= 0 && ret < (ssize_t)bytes) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001891 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
1892 }
Eric Laurentb49b3f62016-02-29 17:59:49 -08001893 if (ret > 0 && !out->playback_started) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001894 compress_start(out->compr);
1895 out->playback_started = 1;
1896 out->offload_state = OFFLOAD_STATE_PLAYING;
1897 }
1898 pthread_mutex_unlock(&out->lock);
1899 return ret;
1900 } else {
1901 if (out->pcm) {
1902 if (out->muted)
1903 memset((void *)buffer, 0, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001904
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001905 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001906
Haynes Mathew George03c40102016-01-29 17:57:48 -08001907 long ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
1908 out->config.rate;
1909 request_out_focus(out, ns);
1910
1911 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
1912 if (use_mmap)
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001913 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07001914 else
1915 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001916
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001917 if (ret == 0)
1918 out->written += bytes / (out->config.channels * sizeof(short));
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07001919
Haynes Mathew George03c40102016-01-29 17:57:48 -08001920 release_out_focus(out, ns);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001921 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001922 }
1923
1924exit:
1925 pthread_mutex_unlock(&out->lock);
1926
1927 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001928 if (out->pcm)
vivek mehta1a9b7c02015-06-25 11:49:38 -07001929 ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930 out_standby(&out->stream.common);
Eric Laurentfdf296a2014-07-03 16:41:51 -07001931 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932 out_get_sample_rate(&out->stream.common));
1933 }
1934 return bytes;
1935}
1936
1937static int out_get_render_position(const struct audio_stream_out *stream,
1938 uint32_t *dsp_frames)
1939{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001940 struct stream_out *out = (struct stream_out *)stream;
1941 *dsp_frames = 0;
1942 if ((out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) && (dsp_frames != NULL)) {
Eric Laurenta1478072015-09-21 17:21:52 -07001943 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001944 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08001945 unsigned long frames = 0;
1946 // TODO: check return value
1947 compress_get_tstamp(out->compr, &frames, &out->sample_rate);
1948 *dsp_frames = (uint32_t)frames;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001949 ALOGVV("%s rendered frames %d sample_rate %d",
1950 __func__, *dsp_frames, out->sample_rate);
1951 }
1952 pthread_mutex_unlock(&out->lock);
1953 return 0;
1954 } else
1955 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956}
1957
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001958static int out_add_audio_effect(const struct audio_stream *stream __unused,
1959 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001960{
1961 return 0;
1962}
1963
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001964static int out_remove_audio_effect(const struct audio_stream *stream __unused,
1965 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001966{
1967 return 0;
1968}
1969
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07001970static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
1971 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001972{
1973 return -EINVAL;
1974}
1975
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001976static int out_get_presentation_position(const struct audio_stream_out *stream,
1977 uint64_t *frames, struct timespec *timestamp)
1978{
1979 struct stream_out *out = (struct stream_out *)stream;
Andy Hung7171da22016-03-08 16:58:42 -08001980 int ret = -EINVAL;
Eric Laurent949a0892013-09-20 09:20:13 -07001981 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001982
Eric Laurenta1478072015-09-21 17:21:52 -07001983 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07001984
Eric Laurent949a0892013-09-20 09:20:13 -07001985 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
1986 if (out->compr != NULL) {
Andy Hung7171da22016-03-08 16:58:42 -08001987 // TODO: check return value
Eric Laurent949a0892013-09-20 09:20:13 -07001988 compress_get_tstamp(out->compr, &dsp_frames,
1989 &out->sample_rate);
1990 ALOGVV("%s rendered frames %ld sample_rate %d",
1991 __func__, dsp_frames, out->sample_rate);
1992 *frames = dsp_frames;
1993 ret = 0;
1994 /* this is the best we can do */
1995 clock_gettime(CLOCK_MONOTONIC, timestamp);
1996 }
1997 } else {
1998 if (out->pcm) {
vivek mehta1a9b7c02015-06-25 11:49:38 -07001999 unsigned int avail;
Eric Laurent949a0892013-09-20 09:20:13 -07002000 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2001 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002002 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002003 // This adjustment accounts for buffering after app processor.
2004 // It is based on estimated DSP latency per use case, rather than exact.
2005 signed_frames -=
2006 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2007
Eric Laurent949a0892013-09-20 09:20:13 -07002008 // It would be unusual for this value to be negative, but check just in case ...
2009 if (signed_frames >= 0) {
2010 *frames = signed_frames;
2011 ret = 0;
2012 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002013 }
2014 }
2015 }
2016
2017 pthread_mutex_unlock(&out->lock);
2018
2019 return ret;
2020}
2021
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002022static int out_set_callback(struct audio_stream_out *stream,
2023 stream_callback_t callback, void *cookie)
2024{
2025 struct stream_out *out = (struct stream_out *)stream;
2026
2027 ALOGV("%s", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002028 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002029 out->offload_callback = callback;
2030 out->offload_cookie = cookie;
2031 pthread_mutex_unlock(&out->lock);
2032 return 0;
2033}
2034
2035static int out_pause(struct audio_stream_out* stream)
2036{
2037 struct stream_out *out = (struct stream_out *)stream;
2038 int status = -ENOSYS;
2039 ALOGV("%s", __func__);
2040 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002041 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002042 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
2043 status = compress_pause(out->compr);
2044 out->offload_state = OFFLOAD_STATE_PAUSED;
2045 }
2046 pthread_mutex_unlock(&out->lock);
2047 }
2048 return status;
2049}
2050
2051static int out_resume(struct audio_stream_out* stream)
2052{
2053 struct stream_out *out = (struct stream_out *)stream;
2054 int status = -ENOSYS;
2055 ALOGV("%s", __func__);
2056 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2057 status = 0;
Eric Laurenta1478072015-09-21 17:21:52 -07002058 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002059 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
2060 status = compress_resume(out->compr);
2061 out->offload_state = OFFLOAD_STATE_PLAYING;
2062 }
2063 pthread_mutex_unlock(&out->lock);
2064 }
2065 return status;
2066}
2067
2068static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2069{
2070 struct stream_out *out = (struct stream_out *)stream;
2071 int status = -ENOSYS;
2072 ALOGV("%s", __func__);
2073 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002074 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002075 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2076 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2077 else
2078 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2079 pthread_mutex_unlock(&out->lock);
2080 }
2081 return status;
2082}
2083
2084static int out_flush(struct audio_stream_out* stream)
2085{
2086 struct stream_out *out = (struct stream_out *)stream;
2087 ALOGV("%s", __func__);
2088 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
Eric Laurenta1478072015-09-21 17:21:52 -07002089 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002090 stop_compressed_output_l(out);
2091 pthread_mutex_unlock(&out->lock);
2092 return 0;
2093 }
2094 return -ENOSYS;
2095}
2096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002097/** audio_stream_in implementation **/
2098static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2099{
2100 struct stream_in *in = (struct stream_in *)stream;
2101
2102 return in->config.rate;
2103}
2104
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002105static int in_set_sample_rate(struct audio_stream *stream __unused, uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106{
2107 return -ENOSYS;
2108}
2109
2110static size_t in_get_buffer_size(const struct audio_stream *stream)
2111{
2112 struct stream_in *in = (struct stream_in *)stream;
2113
Haynes Mathew George03c40102016-01-29 17:57:48 -08002114 return in->config.period_size * in->af_period_multiplier *
2115 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116}
2117
2118static uint32_t in_get_channels(const struct audio_stream *stream)
2119{
2120 struct stream_in *in = (struct stream_in *)stream;
2121
2122 return in->channel_mask;
2123}
2124
vivek mehta4ed66e62016-04-15 23:33:34 -07002125static audio_format_t in_get_format(const struct audio_stream *stream)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002126{
vivek mehta4ed66e62016-04-15 23:33:34 -07002127 struct stream_in *in = (struct stream_in *)stream;
2128 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002129}
2130
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002131static int in_set_format(struct audio_stream *stream __unused, audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002132{
2133 return -ENOSYS;
2134}
2135
2136static int in_standby(struct audio_stream *stream)
2137{
2138 struct stream_in *in = (struct stream_in *)stream;
2139 struct audio_device *adev = in->dev;
2140 int status = 0;
Eric Laurent994a6932013-07-17 11:51:42 -07002141 ALOGV("%s: enter", __func__);
Eric Laurenta1478072015-09-21 17:21:52 -07002142
2143 lock_input_stream(in);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002144
2145 if (!in->standby && in->is_st_session) {
Joe Onorato188b6222016-03-01 11:02:27 -08002146 ALOGV("%s: sound trigger pcm stop lab", __func__);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002147 audio_extn_sound_trigger_stop_lab(in);
2148 in->standby = true;
2149 }
2150
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002151 if (!in->standby) {
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002152 if (adev->adm_deregister_stream)
2153 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
2154
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002155 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002157 if (in->pcm) {
2158 pcm_close(in->pcm);
2159 in->pcm = NULL;
2160 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002161 adev->enable_voicerx = false;
2162 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE );
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002163 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002164 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165 }
2166 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002167 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 return status;
2169}
2170
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002171static int in_dump(const struct audio_stream *stream __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172{
2173 return 0;
2174}
2175
2176static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2177{
2178 struct stream_in *in = (struct stream_in *)stream;
2179 struct audio_device *adev = in->dev;
2180 struct str_parms *parms;
2181 char *str;
2182 char value[32];
2183 int ret, val = 0;
Eric Laurent03f09432014-03-25 18:09:11 -07002184 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002185
Eric Laurent994a6932013-07-17 11:51:42 -07002186 ALOGV("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002187 parms = str_parms_create_str(kvpairs);
2188
2189 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2190
Eric Laurenta1478072015-09-21 17:21:52 -07002191 lock_input_stream(in);
2192
Eric Laurent150dbfe2013-02-27 14:31:02 -08002193 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 if (ret >= 0) {
2195 val = atoi(value);
2196 /* no audio source uses val == 0 */
2197 if ((in->source != val) && (val != 0)) {
2198 in->source = val;
2199 }
2200 }
2201
2202 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
Eric Laurent03f09432014-03-25 18:09:11 -07002203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002204 if (ret >= 0) {
2205 val = atoi(value);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002206 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002207 in->device = val;
2208 /* If recording is in progress, change the tx device to new device */
Haynes Mathew George03c40102016-01-29 17:57:48 -08002209 if (!in->standby) {
2210 ALOGV("update input routing change");
2211 in->routing_change = true;
2212 select_devices(adev, in->usecase);
2213 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214 }
2215 }
2216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002217 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002218 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002219
2220 str_parms_destroy(parms);
Eric Laurent03f09432014-03-25 18:09:11 -07002221 ALOGV("%s: exit: status(%d)", __func__, status);
2222 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223}
2224
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002225static char* in_get_parameters(const struct audio_stream *stream __unused,
2226 const char *keys __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002227{
2228 return strdup("");
2229}
2230
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002231static int in_set_gain(struct audio_stream_in *stream __unused, float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232{
2233 return 0;
2234}
2235
2236static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2237 size_t bytes)
2238{
2239 struct stream_in *in = (struct stream_in *)stream;
2240 struct audio_device *adev = in->dev;
2241 int i, ret = -1;
vivek mehta4ed66e62016-04-15 23:33:34 -07002242 int *int_buf_stream = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002243
Eric Laurenta1478072015-09-21 17:21:52 -07002244 lock_input_stream(in);
2245
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002246 if (in->is_st_session) {
2247 ALOGVV(" %s: reading on st session bytes=%d", __func__, bytes);
2248 /* Read from sound trigger HAL */
2249 audio_extn_sound_trigger_read(in, buffer, bytes);
2250 pthread_mutex_unlock(&in->lock);
2251 return bytes;
2252 }
2253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002255 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002256 ret = start_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002257 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002259 goto exit;
2260 }
2261 in->standby = 0;
2262 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002263
Haynes Mathew George03c40102016-01-29 17:57:48 -08002264 //what's the duration requested by the client?
2265 long ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
2266 in->config.rate;
2267 request_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002268
Haynes Mathew George03c40102016-01-29 17:57:48 -08002269 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002270 if (in->pcm) {
Haynes Mathew George03c40102016-01-29 17:57:48 -08002271 if (use_mmap) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002272 ret = pcm_mmap_read(in->pcm, buffer, bytes);
vivek mehta4ed66e62016-04-15 23:33:34 -07002273 } else {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002274 ret = pcm_read(in->pcm, buffer, bytes);
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002275 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002276 if (ret < 0) {
2277 ALOGE("Failed to read w/err %s", strerror(errno));
2278 ret = -errno;
2279 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002280 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
2281 if (bytes % 4 == 0) {
2282 /* data from DSP comes in 24_8 format, convert it to 8_24 */
2283 int_buf_stream = buffer;
2284 for (size_t itt=0; itt < bytes/4 ; itt++) {
2285 int_buf_stream[itt] >>= 8;
vivek mehta4ed66e62016-04-15 23:33:34 -07002286 }
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002287 } else {
2288 ALOGE("%s: !!! something wrong !!! ... data not 32 bit aligned ", __func__);
2289 ret = -EINVAL;
2290 goto exit;
vivek mehta4ed66e62016-04-15 23:33:34 -07002291 }
2292 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002293 }
2294
Haynes Mathew George03c40102016-01-29 17:57:48 -08002295 release_in_focus(in, ns);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002296
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002297 /*
2298 * Instead of writing zeroes here, we could trust the hardware
2299 * to always provide zeroes when muted.
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002300 * 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 -08002301 */
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002302 if (ret == 0 && adev->mic_muted && in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002303 memset(buffer, 0, bytes);
2304
2305exit:
2306 pthread_mutex_unlock(&in->lock);
2307
2308 if (ret != 0) {
2309 in_standby(&in->stream.common);
2310 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Eric Laurentfdf296a2014-07-03 16:41:51 -07002311 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002312 in_get_sample_rate(&in->stream.common));
Andy Hungc8589872016-03-10 16:37:48 -08002313 memset(buffer, 0, bytes); // clear return data
2314 }
2315 if (bytes > 0) {
Andy Hung6ebe5962016-01-15 17:46:57 -08002316 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002317 }
2318 return bytes;
2319}
2320
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002321static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002322{
2323 return 0;
2324}
2325
Andy Hung6ebe5962016-01-15 17:46:57 -08002326static int in_get_capture_position(const struct audio_stream_in *stream,
2327 int64_t *frames, int64_t *time)
2328{
2329 if (stream == NULL || frames == NULL || time == NULL) {
2330 return -EINVAL;
2331 }
2332 struct stream_in *in = (struct stream_in *)stream;
2333 int ret = -ENOSYS;
2334
2335 lock_input_stream(in);
2336 if (in->pcm) {
2337 struct timespec timestamp;
2338 unsigned int avail;
2339 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2340 *frames = in->frames_read + avail;
2341 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2342 ret = 0;
2343 }
2344 }
2345 pthread_mutex_unlock(&in->lock);
2346 return ret;
2347}
2348
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002349static int add_remove_audio_effect(const struct audio_stream *stream,
2350 effect_handle_t effect,
2351 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002352{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002353 struct stream_in *in = (struct stream_in *)stream;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002354 struct audio_device *adev = in->dev;
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002355 int status = 0;
2356 effect_descriptor_t desc;
2357
2358 status = (*effect)->get_descriptor(effect, &desc);
2359 if (status != 0)
2360 return status;
2361
Eric Laurenta1478072015-09-21 17:21:52 -07002362 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002363 pthread_mutex_lock(&in->dev->lock);
Eric Laurent50a38ed2015-10-14 18:48:06 -07002364 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
vivek mehta733c1df2016-04-04 15:09:24 -07002365 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
Eric Laurent50a38ed2015-10-14 18:48:06 -07002366 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002367 in->enable_aec != enable &&
2368 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2369 in->enable_aec = enable;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002370 if (!enable)
2371 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
vivek mehta733c1df2016-04-04 15:09:24 -07002372 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2373 adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
2374 adev->enable_voicerx = enable;
2375 struct audio_usecase *usecase;
2376 struct listnode *node;
2377 list_for_each(node, &adev->usecase_list) {
2378 usecase = node_to_item(node, struct audio_usecase, list);
2379 if (usecase->type == PCM_PLAYBACK) {
2380 select_devices(adev, usecase->id);
2381 break;
2382 }
Eric Laurentcefbbac2014-09-04 13:54:10 -05002383 }
2384 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002385 if (!in->standby)
2386 select_devices(in->dev, in->usecase);
2387 }
Ravi Kumar Alamanda3ad4e1b2014-06-03 00:08:15 -07002388 if (in->enable_ns != enable &&
2389 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2390 in->enable_ns = enable;
2391 if (!in->standby)
2392 select_devices(in->dev, in->usecase);
2393 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002394 pthread_mutex_unlock(&in->dev->lock);
2395 pthread_mutex_unlock(&in->lock);
2396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002397 return 0;
2398}
2399
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002400static int in_add_audio_effect(const struct audio_stream *stream,
2401 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002402{
Eric Laurent994a6932013-07-17 11:51:42 -07002403 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002404 return add_remove_audio_effect(stream, effect, true);
2405}
2406
2407static int in_remove_audio_effect(const struct audio_stream *stream,
2408 effect_handle_t effect)
2409{
Eric Laurent994a6932013-07-17 11:51:42 -07002410 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002411 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412}
2413
2414static int adev_open_output_stream(struct audio_hw_device *dev,
2415 audio_io_handle_t handle,
2416 audio_devices_t devices,
2417 audio_output_flags_t flags,
2418 struct audio_config *config,
Eric Laurent91975a62014-07-27 17:15:50 -07002419 struct audio_stream_out **stream_out,
2420 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002421{
2422 struct audio_device *adev = (struct audio_device *)dev;
2423 struct stream_out *out;
2424 int i, ret;
2425
Eric Laurent994a6932013-07-17 11:51:42 -07002426 ALOGV("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427 __func__, config->sample_rate, config->channel_mask, devices, flags);
2428 *stream_out = NULL;
2429 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2430
2431 if (devices == AUDIO_DEVICE_NONE)
2432 devices = AUDIO_DEVICE_OUT_SPEAKER;
2433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002434 out->flags = flags;
2435 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002436 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002437 out->format = config->format;
2438 out->sample_rate = config->sample_rate;
2439 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2440 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002441 out->handle = handle;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002442
2443 /* Init use case and pcm_config */
2444 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
Eric Laurent7f245042013-09-30 19:22:50 -07002445 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002446 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002447 pthread_mutex_lock(&adev->lock);
2448 ret = read_hdmi_channel_masks(out);
2449 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002450 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002451 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002452
2453 if (config->sample_rate == 0)
2454 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2455 if (config->channel_mask == 0)
2456 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
Eric Laurentad1cec22015-12-16 10:12:27 -08002457 if (config->format == AUDIO_FORMAT_DEFAULT)
2458 config->format = AUDIO_FORMAT_PCM_16_BIT;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002459
2460 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002461 out->sample_rate = config->sample_rate;
Eric Laurentad1cec22015-12-16 10:12:27 -08002462 out->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002463 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2464 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 out->config.rate = config->sample_rate;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002466 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002468 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
2469 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2470 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2471 ALOGE("%s: Unsupported Offload information", __func__);
2472 ret = -EINVAL;
2473 goto error_open;
2474 }
2475 if (!is_supported_format(config->offload_info.format)) {
2476 ALOGE("%s: Unsupported audio format", __func__);
2477 ret = -EINVAL;
2478 goto error_open;
2479 }
2480
2481 out->compr_config.codec = (struct snd_codec *)
2482 calloc(1, sizeof(struct snd_codec));
2483
2484 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
2485 if (config->offload_info.channel_mask)
2486 out->channel_mask = config->offload_info.channel_mask;
2487 else if (config->channel_mask)
2488 out->channel_mask = config->channel_mask;
2489 out->format = config->offload_info.format;
2490 out->sample_rate = config->offload_info.sample_rate;
2491
2492 out->stream.set_callback = out_set_callback;
2493 out->stream.pause = out_pause;
2494 out->stream.resume = out_resume;
2495 out->stream.drain = out_drain;
2496 out->stream.flush = out_flush;
2497
2498 out->compr_config.codec->id =
2499 get_snd_codec_id(config->offload_info.format);
2500 out->compr_config.fragment_size = COMPRESS_OFFLOAD_FRAGMENT_SIZE;
2501 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent1ccf3972014-10-23 14:42:59 -07002502 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002503 out->compr_config.codec->bit_rate =
2504 config->offload_info.bit_rate;
2505 out->compr_config.codec->ch_in =
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002506 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002507 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
2508
2509 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2510 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002511
2512 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002513 create_offload_callback_thread(out);
2514 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2515 __func__, config->offload_info.version,
2516 config->offload_info.bit_rate);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002517 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2518 if (config->sample_rate == 0)
2519 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2520 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2521 config->sample_rate != 8000) {
2522 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2523 ret = -EINVAL;
2524 goto error_open;
2525 }
2526 out->sample_rate = config->sample_rate;
2527 out->config.rate = config->sample_rate;
2528 if (config->format == AUDIO_FORMAT_DEFAULT)
2529 config->format = AUDIO_FORMAT_PCM_16_BIT;
2530 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2531 config->format = AUDIO_FORMAT_PCM_16_BIT;
2532 ret = -EINVAL;
2533 goto error_open;
2534 }
2535 out->format = config->format;
2536 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2537 out->config = pcm_config_afe_proxy_playback;
2538 adev->voice_tx_output = out;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002539 } else {
Andy Hung6fcba9c2014-03-18 11:53:32 -07002540 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2541 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2542 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamandaf78a4d92015-04-24 15:18:23 -07002543 } else if (out->flags & AUDIO_OUTPUT_FLAG_TTS) {
2544 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
2545 out->config = pcm_config_deep_buffer;
Ravi Kumar Alamanda2bc7b022015-06-25 20:08:01 -07002546 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
2547 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002548 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL, out->flags);
2549 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2550 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Andy Hung6fcba9c2014-03-18 11:53:32 -07002551 } else {
2552 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2553 out->config = pcm_config_low_latency;
2554 }
2555 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2556 if (k_enable_extended_precision
2557 && pcm_params_format_test(adev->use_case_table[out->usecase],
2558 pcm_format_from_audio_format(config->format))) {
2559 out->config.format = pcm_format_from_audio_format(config->format);
2560 /* out->format already set to config->format */
2561 } else {
2562 /* deny the externally proposed config format
2563 * and use the one specified in audio_hw layer configuration.
2564 * Note: out->format is returned by out->stream.common.get_format()
2565 * and is used to set config->format in the code several lines below.
2566 */
2567 out->format = audio_format_from_pcm_format(out->config.format);
2568 }
2569 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002570 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002571 }
Andy Hung6fcba9c2014-03-18 11:53:32 -07002572 ALOGV("%s: Usecase(%s) config->format %#x out->config.format %#x\n",
2573 __func__, use_case_table[out->usecase], config->format, out->config.format);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002575 if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002576 if (adev->primary_output == NULL)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002577 adev->primary_output = out;
2578 else {
2579 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002580 ret = -EEXIST;
2581 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002582 }
2583 }
2584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585 /* Check if this usecase is already existing */
2586 pthread_mutex_lock(&adev->lock);
2587 if (get_usecase_from_list(adev, out->usecase) != NULL) {
2588 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002590 ret = -EEXIST;
2591 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592 }
2593 pthread_mutex_unlock(&adev->lock);
2594
2595 out->stream.common.get_sample_rate = out_get_sample_rate;
2596 out->stream.common.set_sample_rate = out_set_sample_rate;
2597 out->stream.common.get_buffer_size = out_get_buffer_size;
2598 out->stream.common.get_channels = out_get_channels;
2599 out->stream.common.get_format = out_get_format;
2600 out->stream.common.set_format = out_set_format;
2601 out->stream.common.standby = out_standby;
2602 out->stream.common.dump = out_dump;
2603 out->stream.common.set_parameters = out_set_parameters;
2604 out->stream.common.get_parameters = out_get_parameters;
2605 out->stream.common.add_audio_effect = out_add_audio_effect;
2606 out->stream.common.remove_audio_effect = out_remove_audio_effect;
2607 out->stream.get_latency = out_get_latency;
2608 out->stream.set_volume = out_set_volume;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002609#ifdef NO_AUDIO_OUT
2610 out->stream.write = out_write_for_no_output;
2611#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 out->stream.write = out_write;
Uday Kishore Pasupuleticec8ad82015-04-15 10:34:06 -07002613#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614 out->stream.get_render_position = out_get_render_position;
2615 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002616 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002617
Haynes Mathew George03c40102016-01-29 17:57:48 -08002618 out->af_period_multiplier = out->realtime ? af_period_multiplier : 1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002619 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07002620 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002621 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002623 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07002624 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002625 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
2626
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 config->format = out->stream.common.get_format(&out->stream.common);
2628 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
2629 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
2630
2631 *stream_out = &out->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002632 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002634
2635error_open:
2636 free(out);
2637 *stream_out = NULL;
Eric Laurent2bafff12016-03-17 12:17:23 -07002638 ALOGW("%s: exit: ret %d", __func__, ret);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002639 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640}
2641
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002642static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643 struct audio_stream_out *stream)
2644{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002645 struct stream_out *out = (struct stream_out *)stream;
2646 struct audio_device *adev = out->dev;
2647
Eric Laurent994a6932013-07-17 11:51:42 -07002648 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 out_standby(&stream->common);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002650 if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
2651 destroy_offload_callback_thread(out);
2652
2653 if (out->compr_config.codec != NULL)
2654 free(out->compr_config.codec);
2655 }
Ravi Kumar Alamandaa4fc9022014-10-08 18:57:46 -07002656
2657 if (adev->voice_tx_output == out)
2658 adev->voice_tx_output = NULL;
2659
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002660 pthread_cond_destroy(&out->cond);
2661 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07002663 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664}
2665
2666static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
2667{
2668 struct audio_device *adev = (struct audio_device *)dev;
2669 struct str_parms *parms;
2670 char *str;
2671 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002672 int val;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 int ret;
Eric Laurent03f09432014-03-25 18:09:11 -07002674 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675
Joe Onorato188b6222016-03-01 11:02:27 -08002676 ALOGV("%s: enter: %s", __func__, kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002677
2678 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679
2680 parms = str_parms_create_str(kvpairs);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002681 status = voice_set_parameters(adev, parms);
2682 if (status != 0) {
2683 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684 }
2685
2686 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
2687 if (ret >= 0) {
Ravi Kumar Alamandae258e682015-06-25 13:32:42 -07002688 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2690 adev->bluetooth_nrec = true;
2691 else
2692 adev->bluetooth_nrec = false;
2693 }
2694
2695 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
2696 if (ret >= 0) {
2697 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
2698 adev->screen_off = false;
2699 else
2700 adev->screen_off = true;
2701 }
2702
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002703 ret = str_parms_get_int(parms, "rotation", &val);
2704 if (ret >= 0) {
2705 bool reverse_speakers = false;
2706 switch(val) {
2707 // FIXME: note that the code below assumes that the speakers are in the correct placement
2708 // relative to the user when the device is rotated 90deg from its default rotation. This
2709 // assumption is device-specific, not platform-specific like this code.
2710 case 270:
2711 reverse_speakers = true;
2712 break;
2713 case 0:
2714 case 90:
2715 case 180:
2716 break;
2717 default:
2718 ALOGE("%s: unexpected rotation of %d", __func__, val);
Eric Laurent03f09432014-03-25 18:09:11 -07002719 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002720 }
Eric Laurent03f09432014-03-25 18:09:11 -07002721 if (status == 0) {
Ravi Kumar Alamanda1f60cf82015-04-23 19:45:17 -07002722 platform_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002723 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07002724 }
2725
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002726 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
2727 if (ret >= 0) {
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002728 adev->bt_wb_speech_enabled = !strcmp(value, AUDIO_PARAMETER_VALUE_ON);
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07002729 }
2730
Ravi Kumar Alamanda8e6e98f2013-11-05 15:57:39 -08002731 audio_extn_hfp_set_parameters(adev, parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002732done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733 str_parms_destroy(parms);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002734 pthread_mutex_unlock(&adev->lock);
Eric Laurent03f09432014-03-25 18:09:11 -07002735 ALOGV("%s: exit with code(%d)", __func__, status);
2736 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737}
2738
2739static char* adev_get_parameters(const struct audio_hw_device *dev,
2740 const char *keys)
2741{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002742 struct audio_device *adev = (struct audio_device *)dev;
2743 struct str_parms *reply = str_parms_create();
2744 struct str_parms *query = str_parms_create_str(keys);
2745 char *str;
2746
2747 pthread_mutex_lock(&adev->lock);
2748
2749 voice_get_parameters(adev, query, reply);
2750 str = str_parms_to_str(reply);
2751 str_parms_destroy(query);
2752 str_parms_destroy(reply);
2753
2754 pthread_mutex_unlock(&adev->lock);
2755 ALOGV("%s: exit: returns - %s", __func__, str);
2756 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757}
2758
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002759static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760{
2761 return 0;
2762}
2763
Haynes Mathew George5191a852013-09-11 14:19:36 -07002764static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
2765{
2766 int ret;
2767 struct audio_device *adev = (struct audio_device *)dev;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002768
Eric Laurent4cc4ce12014-09-10 13:21:01 -05002769 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
2770
Haynes Mathew George5191a852013-09-11 14:19:36 -07002771 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002772 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07002773 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002774
Haynes Mathew George5191a852013-09-11 14:19:36 -07002775 return ret;
2776}
2777
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002778static int adev_set_master_volume(struct audio_hw_device *dev __unused, float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779{
2780 return -ENOSYS;
2781}
2782
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002783static int adev_get_master_volume(struct audio_hw_device *dev __unused,
2784 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002785{
2786 return -ENOSYS;
2787}
2788
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002789static int adev_set_master_mute(struct audio_hw_device *dev __unused, bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790{
2791 return -ENOSYS;
2792}
2793
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002794static int adev_get_master_mute(struct audio_hw_device *dev __unused, bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795{
2796 return -ENOSYS;
2797}
2798
2799static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
2800{
2801 struct audio_device *adev = (struct audio_device *)dev;
2802
2803 pthread_mutex_lock(&adev->lock);
2804 if (adev->mode != mode) {
Eric Laurent2bafff12016-03-17 12:17:23 -07002805 ALOGD("%s: mode %d", __func__, (int)mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 adev->mode = mode;
Ravi Kumar Alamanda36886fc2014-09-29 13:41:51 -07002807 if ((mode == AUDIO_MODE_NORMAL || mode == AUDIO_MODE_IN_COMMUNICATION) &&
2808 voice_is_in_call(adev)) {
2809 voice_stop_call(adev);
2810 adev->current_call_output = NULL;
2811 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 }
2813 pthread_mutex_unlock(&adev->lock);
Eric Laurent0499d4f2014-08-25 22:39:29 -05002814
2815 audio_extn_extspk_set_mode(adev->extspk, mode);
2816
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002817 return 0;
2818}
2819
2820static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
2821{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002822 int ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002823 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824
Eric Laurent2bafff12016-03-17 12:17:23 -07002825 ALOGD("%s: state %d", __func__, (int)state);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002826 pthread_mutex_lock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002827 ret = voice_set_mic_mute(adev, state);
Eric Laurent7b2b5ab2014-09-14 12:29:59 -07002828 adev->mic_muted = state;
Eric Laurenta609e8e2014-06-18 02:15:17 +00002829 pthread_mutex_unlock(&adev->lock);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002830
2831 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832}
2833
2834static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
2835{
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002836 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837 return 0;
2838}
2839
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07002840static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002841 const struct audio_config *config)
2842{
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002843 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002845 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
2846 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002847}
2848
2849static int adev_open_input_stream(struct audio_hw_device *dev,
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002850 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002851 audio_devices_t devices,
2852 struct audio_config *config,
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002853 struct audio_stream_in **stream_in,
Eric Laurent91975a62014-07-27 17:15:50 -07002854 audio_input_flags_t flags,
2855 const char *address __unused,
Eric Laurentcefbbac2014-09-04 13:54:10 -05002856 audio_source_t source )
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857{
2858 struct audio_device *adev = (struct audio_device *)dev;
2859 struct stream_in *in;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002860 int ret = 0, buffer_size, frame_size;
Eric Laurent0de8d1f2014-07-01 20:34:45 -07002861 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002862 bool is_low_latency = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863
Eric Laurent994a6932013-07-17 11:51:42 -07002864 ALOGV("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002865 *stream_in = NULL;
2866 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
2867 return -EINVAL;
2868
2869 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
2870
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002871 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurenta1478072015-09-21 17:21:52 -07002872 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07002873
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002874 in->stream.common.get_sample_rate = in_get_sample_rate;
2875 in->stream.common.set_sample_rate = in_set_sample_rate;
2876 in->stream.common.get_buffer_size = in_get_buffer_size;
2877 in->stream.common.get_channels = in_get_channels;
2878 in->stream.common.get_format = in_get_format;
2879 in->stream.common.set_format = in_set_format;
2880 in->stream.common.standby = in_standby;
2881 in->stream.common.dump = in_dump;
2882 in->stream.common.set_parameters = in_set_parameters;
2883 in->stream.common.get_parameters = in_get_parameters;
2884 in->stream.common.add_audio_effect = in_add_audio_effect;
2885 in->stream.common.remove_audio_effect = in_remove_audio_effect;
2886 in->stream.set_gain = in_set_gain;
2887 in->stream.read = in_read;
2888 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6ebe5962016-01-15 17:46:57 -08002889 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890
2891 in->device = devices;
Eric Laurentcefbbac2014-09-04 13:54:10 -05002892 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002893 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894 in->standby = 1;
2895 in->channel_mask = config->channel_mask;
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002896 in->capture_handle = handle;
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07002897 in->flags = flags;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002898
vivek mehta57ff9b52016-04-28 14:13:08 -07002899 // restrict 24 bit capture for unprocessed source only
2900 // for other sources if 24 bit requested reject 24 and set 16 bit capture only
2901 if (config->format == AUDIO_FORMAT_DEFAULT) {
vivek mehta4ed66e62016-04-15 23:33:34 -07002902 config->format = AUDIO_FORMAT_PCM_16_BIT;
vivek mehta57ff9b52016-04-28 14:13:08 -07002903 } else if (config->format == AUDIO_FORMAT_PCM_FLOAT ||
2904 config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
2905 config->format == AUDIO_FORMAT_PCM_8_24_BIT) {
2906 bool ret_error = false;
2907 /* 24 bit is restricted to UNPROCESSED source only,also format supported
2908 from HAL is 8_24
2909 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
2910 8_24 return error indicating supported format is 8_24
2911 *> In case of any other source requesting 24 bit or float return error
2912 indicating format supported is 16 bit only.
vivek mehta4ed66e62016-04-15 23:33:34 -07002913
vivek mehta57ff9b52016-04-28 14:13:08 -07002914 on error flinger will retry with supported format passed
2915 */
2916 if (source != AUDIO_SOURCE_UNPROCESSED) {
2917 config->format = AUDIO_FORMAT_PCM_16_BIT;
2918 ret_error = true;
2919 } else if (config->format != AUDIO_FORMAT_PCM_8_24_BIT) {
2920 config->format = AUDIO_FORMAT_PCM_8_24_BIT;
2921 ret_error = true;
2922 }
2923
2924 if (ret_error) {
2925 ret = -EINVAL;
2926 goto err_open;
2927 }
vivek mehta4ed66e62016-04-15 23:33:34 -07002928 }
2929
vivek mehta57ff9b52016-04-28 14:13:08 -07002930 in->format = config->format;
2931
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932 /* Update config params with the requested sample rate and channels */
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002933 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
2934 if (config->sample_rate == 0)
2935 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2936 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2937 config->sample_rate != 8000) {
2938 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2939 ret = -EINVAL;
2940 goto err_open;
2941 }
vivek mehta4ed66e62016-04-15 23:33:34 -07002942
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002943 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2944 config->format = AUDIO_FORMAT_PCM_16_BIT;
2945 ret = -EINVAL;
2946 goto err_open;
2947 }
2948
2949 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
2950 in->config = pcm_config_afe_proxy_record;
2951 } else {
2952 in->usecase = USECASE_AUDIO_RECORD;
2953 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
2954 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
2955 is_low_latency = true;
Glenn Kasten4f993392014-05-14 07:30:48 -07002956#if LOW_LATENCY_CAPTURE_USE_CASE
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002957 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
Glenn Kasten4f993392014-05-14 07:30:48 -07002958#endif
Haynes Mathew George03c40102016-01-29 17:57:48 -08002959 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002960 }
Ravi Kumar Alamanda99c752d2014-08-20 17:55:26 -07002961
Haynes Mathew George03c40102016-01-29 17:57:48 -08002962 in->config = in->realtime ? pcm_config_audio_capture_rt :
2963 pcm_config_audio_capture;
2964
vivek mehta4ed66e62016-04-15 23:33:34 -07002965 if (config->format == AUDIO_FORMAT_PCM_8_24_BIT)
2966 in->config.format = PCM_FORMAT_S24_LE;
2967
Haynes Mathew George03c40102016-01-29 17:57:48 -08002968 if (!in->realtime) {
2969 frame_size = audio_stream_in_frame_size(&in->stream);
2970 buffer_size = get_input_buffer_size(config->sample_rate,
2971 config->format,
2972 channel_count,
Eric Laurentf8b50aa2016-05-06 11:03:53 -07002973 is_low_latency);
Haynes Mathew George03c40102016-01-29 17:57:48 -08002974 in->config.period_size = buffer_size / frame_size;
2975 } // period size is left untouched for rt mode playback
Glenn Kasten68e79ce2014-07-15 10:56:59 -07002976 }
Haynes Mathew George03c40102016-01-29 17:57:48 -08002977
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002978 in->config.channels = channel_count;
Haynes Mathew George03c40102016-01-29 17:57:48 -08002979 if (in->realtime) {
2980 in->af_period_multiplier = af_period_multiplier;
2981 } else {
2982 in->config.rate = config->sample_rate;
2983 in->af_period_multiplier = 1;
2984 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07002986 /* This stream could be for sound trigger lab,
2987 get sound trigger pcm if present */
2988 audio_extn_sound_trigger_check_and_get_session(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989
2990 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07002991 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002992 return 0;
2993
2994err_open:
2995 free(in);
2996 *stream_in = NULL;
2997 return ret;
2998}
2999
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003000static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001 struct audio_stream_in *stream)
3002{
Eric Laurent994a6932013-07-17 11:51:42 -07003003 ALOGV("%s", __func__);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003004
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 in_standby(&stream->common);
3006 free(stream);
3007
3008 return;
3009}
3010
Haynes Mathew Georgecc9649b2014-06-10 15:08:39 -07003011static int adev_dump(const audio_hw_device_t *device __unused, int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003012{
3013 return 0;
3014}
3015
Andy Hung31aca912014-03-20 17:14:59 -07003016/* verifies input and output devices and their capabilities.
3017 *
3018 * This verification is required when enabling extended bit-depth or
3019 * sampling rates, as not all qcom products support it.
3020 *
3021 * Suitable for calling only on initialization such as adev_open().
3022 * It fills the audio_device use_case_table[] array.
3023 *
3024 * Has a side-effect that it needs to configure audio routing / devices
3025 * in order to power up the devices and read the device parameters.
3026 * It does not acquire any hw device lock. Should restore the devices
3027 * back to "normal state" upon completion.
3028 */
3029static int adev_verify_devices(struct audio_device *adev)
3030{
3031 /* enumeration is a bit difficult because one really wants to pull
3032 * the use_case, device id, etc from the hidden pcm_device_table[].
3033 * In this case there are the following use cases and device ids.
3034 *
3035 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3036 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3037 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3038 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3039 * [USECASE_AUDIO_RECORD] = {0, 0},
3040 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3041 * [USECASE_VOICE_CALL] = {2, 2},
3042 *
3043 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3044 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3045 */
3046
3047 /* should be the usecases enabled in adev_open_input_stream() */
3048 static const int test_in_usecases[] = {
3049 USECASE_AUDIO_RECORD,
3050 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3051 };
3052 /* should be the usecases enabled in adev_open_output_stream()*/
3053 static const int test_out_usecases[] = {
3054 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3055 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3056 };
3057 static const usecase_type_t usecase_type_by_dir[] = {
3058 PCM_PLAYBACK,
3059 PCM_CAPTURE,
3060 };
3061 static const unsigned flags_by_dir[] = {
3062 PCM_OUT,
3063 PCM_IN,
3064 };
3065
3066 size_t i;
3067 unsigned dir;
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003068 const unsigned card_id = adev->snd_card;
Andy Hung31aca912014-03-20 17:14:59 -07003069 char info[512]; /* for possible debug info */
3070
3071 for (dir = 0; dir < 2; ++dir) {
3072 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3073 const unsigned flags_dir = flags_by_dir[dir];
3074 const size_t testsize =
3075 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3076 const int *testcases =
3077 dir ? test_in_usecases : test_out_usecases;
3078 const audio_devices_t audio_device =
3079 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3080
3081 for (i = 0; i < testsize; ++i) {
3082 const audio_usecase_t audio_usecase = testcases[i];
3083 int device_id;
3084 snd_device_t snd_device;
3085 struct pcm_params **pparams;
3086 struct stream_out out;
3087 struct stream_in in;
3088 struct audio_usecase uc_info;
3089 int retval;
3090
3091 pparams = &adev->use_case_table[audio_usecase];
3092 pcm_params_free(*pparams); /* can accept null input */
3093 *pparams = NULL;
3094
3095 /* find the device ID for the use case (signed, for error) */
3096 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3097 if (device_id < 0)
3098 continue;
3099
3100 /* prepare structures for device probing */
3101 memset(&uc_info, 0, sizeof(uc_info));
3102 uc_info.id = audio_usecase;
3103 uc_info.type = usecase_type;
3104 if (dir) {
3105 adev->active_input = &in;
3106 memset(&in, 0, sizeof(in));
3107 in.device = audio_device;
3108 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3109 uc_info.stream.in = &in;
3110 } else {
3111 adev->active_input = NULL;
3112 }
3113 memset(&out, 0, sizeof(out));
3114 out.devices = audio_device; /* only field needed in select_devices */
3115 uc_info.stream.out = &out;
3116 uc_info.devices = audio_device;
3117 uc_info.in_snd_device = SND_DEVICE_NONE;
3118 uc_info.out_snd_device = SND_DEVICE_NONE;
3119 list_add_tail(&adev->usecase_list, &uc_info.list);
3120
3121 /* select device - similar to start_(in/out)put_stream() */
3122 retval = select_devices(adev, audio_usecase);
3123 if (retval >= 0) {
3124 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3125#if LOG_NDEBUG == 0
3126 if (*pparams) {
3127 ALOGV("%s: (%s) card %d device %d", __func__,
3128 dir ? "input" : "output", card_id, device_id);
3129 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Andy Hung31aca912014-03-20 17:14:59 -07003130 } else {
3131 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3132 }
3133#endif
3134 }
3135
3136 /* deselect device - similar to stop_(in/out)put_stream() */
3137 /* 1. Get and set stream specific mixer controls */
Glenn Kastene7137302014-04-28 15:12:18 -07003138 retval = disable_audio_route(adev, &uc_info);
Andy Hung31aca912014-03-20 17:14:59 -07003139 /* 2. Disable the rx device */
3140 retval = disable_snd_device(adev,
Glenn Kastene7137302014-04-28 15:12:18 -07003141 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
Andy Hung31aca912014-03-20 17:14:59 -07003142 list_remove(&uc_info.list);
3143 }
3144 }
3145 adev->active_input = NULL; /* restore adev state */
3146 return 0;
3147}
3148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149static int adev_close(hw_device_t *device)
3150{
Andy Hung31aca912014-03-20 17:14:59 -07003151 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152 struct audio_device *adev = (struct audio_device *)device;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003153
3154 if (!adev)
3155 return 0;
3156
3157 pthread_mutex_lock(&adev_init_lock);
3158
3159 if ((--audio_device_ref_count) == 0) {
3160 audio_route_free(adev->audio_route);
3161 free(adev->snd_dev_ref_cnt);
3162 platform_deinit(adev->platform);
3163 audio_extn_extspk_deinit(adev->extspk);
3164 audio_extn_sound_trigger_deinit(adev);
3165 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3166 pcm_params_free(adev->use_case_table[i]);
3167 }
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003168 if (adev->adm_deinit)
3169 adev->adm_deinit(adev->adm_data);
vivek mehta1a9b7c02015-06-25 11:49:38 -07003170 free(device);
Andy Hung31aca912014-03-20 17:14:59 -07003171 }
vivek mehta1a9b7c02015-06-25 11:49:38 -07003172
3173 pthread_mutex_unlock(&adev_init_lock);
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003174
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 return 0;
3176}
3177
Glenn Kasten4f993392014-05-14 07:30:48 -07003178/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3179 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3180 * just that it _might_ work.
3181 */
3182static int period_size_is_plausible_for_low_latency(int period_size)
3183{
3184 switch (period_size) {
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003185 case 48:
3186 case 96:
3187 case 144:
Glenn Kasten4f993392014-05-14 07:30:48 -07003188 case 160:
Glenn Kasten5b5d04e2015-04-09 09:43:29 -07003189 case 192:
Glenn Kasten4f993392014-05-14 07:30:48 -07003190 case 240:
3191 case 320:
3192 case 480:
3193 return 1;
3194 default:
3195 return 0;
3196 }
3197}
3198
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199static int adev_open(const hw_module_t *module, const char *name,
3200 hw_device_t **device)
3201{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003202 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203
Eric Laurent2bafff12016-03-17 12:17:23 -07003204 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003205 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003206 pthread_mutex_lock(&adev_init_lock);
3207 if (audio_device_ref_count != 0) {
3208 *device = &adev->device.common;
3209 audio_device_ref_count++;
3210 ALOGV("%s: returning existing instance of adev", __func__);
3211 ALOGV("%s: exit", __func__);
3212 pthread_mutex_unlock(&adev_init_lock);
3213 return 0;
3214 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003215 adev = calloc(1, sizeof(struct audio_device));
3216
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003217 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3220 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3221 adev->device.common.module = (struct hw_module_t *)module;
3222 adev->device.common.close = adev_close;
3223
3224 adev->device.init_check = adev_init_check;
3225 adev->device.set_voice_volume = adev_set_voice_volume;
3226 adev->device.set_master_volume = adev_set_master_volume;
3227 adev->device.get_master_volume = adev_get_master_volume;
3228 adev->device.set_master_mute = adev_set_master_mute;
3229 adev->device.get_master_mute = adev_get_master_mute;
3230 adev->device.set_mode = adev_set_mode;
3231 adev->device.set_mic_mute = adev_set_mic_mute;
3232 adev->device.get_mic_mute = adev_get_mic_mute;
3233 adev->device.set_parameters = adev_set_parameters;
3234 adev->device.get_parameters = adev_get_parameters;
3235 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3236 adev->device.open_output_stream = adev_open_output_stream;
3237 adev->device.close_output_stream = adev_close_output_stream;
3238 adev->device.open_input_stream = adev_open_input_stream;
3239 adev->device.close_input_stream = adev_close_input_stream;
3240 adev->device.dump = adev_dump;
3241
3242 /* Set the default route before the PCM stream is opened */
3243 pthread_mutex_lock(&adev->lock);
3244 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003245 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003246 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003247 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003248 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003249 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07003250 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Vineeta Srivastava4b89e372014-06-19 14:21:42 -07003251 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003252 list_init(&adev->usecase_list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253 pthread_mutex_unlock(&adev->lock);
3254
3255 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003256 adev->platform = platform_init(adev);
3257 if (!adev->platform) {
3258 free(adev->snd_dev_ref_cnt);
3259 free(adev);
3260 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3261 *device = NULL;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003262 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003263 return -EINVAL;
3264 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003265
Eric Laurent0499d4f2014-08-25 22:39:29 -05003266 adev->extspk = audio_extn_extspk_init(adev);
Ravi Kumar Alamandaa417cc52015-05-01 16:41:56 -07003267 audio_extn_sound_trigger_init(adev);
Eric Laurent0499d4f2014-08-25 22:39:29 -05003268
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003269 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3270 if (adev->visualizer_lib == NULL) {
3271 ALOGW("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3272 } else {
3273 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3274 adev->visualizer_start_output =
3275 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3276 "visualizer_hal_start_output");
3277 adev->visualizer_stop_output =
3278 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
3279 "visualizer_hal_stop_output");
Eric Laurentc4aef752013-09-12 17:45:53 -07003280 }
3281
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003282 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3283 if (adev->offload_effects_lib == NULL) {
3284 ALOGW("%s: DLOPEN failed for %s", __func__,
3285 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3286 } else {
3287 ALOGV("%s: DLOPEN successful for %s", __func__,
3288 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3289 adev->offload_effects_start_output =
3290 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3291 "offload_effects_bundle_hal_start_output");
3292 adev->offload_effects_stop_output =
3293 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3294 "offload_effects_bundle_hal_stop_output");
Haynes Mathew George41f86652014-06-17 14:22:15 -07003295 }
3296
Glenn Kasten6d53bfd2016-04-04 16:58:03 -07003297 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
3298 if (adev->adm_lib == NULL) {
3299 ALOGW("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
3300 } else {
3301 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
3302 adev->adm_init = (adm_init_t)
3303 dlsym(adev->adm_lib, "adm_init");
3304 adev->adm_deinit = (adm_deinit_t)
3305 dlsym(adev->adm_lib, "adm_deinit");
3306 adev->adm_register_input_stream = (adm_register_input_stream_t)
3307 dlsym(adev->adm_lib, "adm_register_input_stream");
3308 adev->adm_register_output_stream = (adm_register_output_stream_t)
3309 dlsym(adev->adm_lib, "adm_register_output_stream");
3310 adev->adm_deregister_stream = (adm_deregister_stream_t)
3311 dlsym(adev->adm_lib, "adm_deregister_stream");
3312 adev->adm_request_focus = (adm_request_focus_t)
3313 dlsym(adev->adm_lib, "adm_request_focus");
3314 adev->adm_abandon_focus = (adm_abandon_focus_t)
3315 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George03c40102016-01-29 17:57:48 -08003316 adev->adm_set_config = (adm_set_config_t)
3317 dlsym(adev->adm_lib, "adm_set_config");
3318 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
3319 dlsym(adev->adm_lib, "adm_request_focus_v2");
3320 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
3321 dlsym(adev->adm_lib, "adm_is_noirq_avail");
3322 adev->adm_on_routing_change = (adm_on_routing_change_t)
3323 dlsym(adev->adm_lib, "adm_on_routing_change");
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003324 }
3325
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003326 adev->bt_wb_speech_enabled = false;
Eric Laurentcefbbac2014-09-04 13:54:10 -05003327 adev->enable_voicerx = false;
Ravi Kumar Alamanda9f306542014-04-02 15:11:49 -07003328
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003329 *device = &adev->device.common;
vivek mehta1a9b7c02015-06-25 11:49:38 -07003330
Andy Hung31aca912014-03-20 17:14:59 -07003331 if (k_enable_extended_precision)
3332 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333
Glenn Kasten4f993392014-05-14 07:30:48 -07003334 char value[PROPERTY_VALUE_MAX];
3335 int trial;
3336 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3337 trial = atoi(value);
3338 if (period_size_is_plausible_for_low_latency(trial)) {
3339 pcm_config_low_latency.period_size = trial;
3340 pcm_config_low_latency.start_threshold = trial / 4;
3341 pcm_config_low_latency.avail_min = trial / 4;
3342 configured_low_latency_capture_period_size = trial;
3343 }
3344 }
3345 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3346 trial = atoi(value);
3347 if (period_size_is_plausible_for_low_latency(trial)) {
3348 configured_low_latency_capture_period_size = trial;
3349 }
3350 }
3351
vivek mehta1a9b7c02015-06-25 11:49:38 -07003352 audio_device_ref_count++;
Haynes Mathew George03c40102016-01-29 17:57:48 -08003353
3354 if (property_get("audio_hal.period_multiplier", value, NULL) > 0) {
3355 af_period_multiplier = atoi(value);
3356 if (af_period_multiplier < 0) {
3357 af_period_multiplier = 2;
3358 } else if (af_period_multiplier > 4) {
3359 af_period_multiplier = 4;
3360 }
3361 ALOGV("new period_multiplier = %d", af_period_multiplier);
3362 }
3363
vivek mehta1a9b7c02015-06-25 11:49:38 -07003364 pthread_mutex_unlock(&adev_init_lock);
3365
Haynes Mathew George88e6fb22015-08-19 11:51:34 -07003366 if (adev->adm_init)
3367 adev->adm_data = adev->adm_init();
3368
Ravi Kumar Alamanda533bb722015-09-23 13:47:03 -07003369 audio_extn_perf_lock_init();
3370
Eric Laurent2bafff12016-03-17 12:17:23 -07003371 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003372 return 0;
3373}
3374
3375static struct hw_module_methods_t hal_module_methods = {
3376 .open = adev_open,
3377};
3378
3379struct audio_module HAL_MODULE_INFO_SYM = {
3380 .common = {
3381 .tag = HARDWARE_MODULE_TAG,
3382 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3383 .hal_api_version = HARDWARE_HAL_API_VERSION,
3384 .id = AUDIO_HARDWARE_MODULE_ID,
3385 .name = "QCOM Audio HAL",
3386 .author = "Code Aurora Forum",
3387 .methods = &hal_module_methods,
3388 },
3389};