blob: bfe0006093ac82b646834938dbac8ff115acec95 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_primary"
Steve Kondik5a447012014-12-02 16:04:20 -080021//#define LOG_NDEBUG 0
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070022/*#define VERY_VERY_VERBOSE_LOGGING*/
23#ifdef VERY_VERY_VERBOSE_LOGGING
24#define ALOGVV ALOGV
25#else
26#define ALOGVV(a...) do { } while(0)
27#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080028#include <errno.h>
29#include <pthread.h>
30#include <stdint.h>
31#include <sys/time.h>
32#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080033#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070034#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070035#include <sys/resource.h>
36#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
39#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>
Steve Kondik3abbbc82014-11-29 14:14:43 -080045#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"
Eric Laurentb23d5282013-05-14 15:27:20 -070050#include "platform_api.h"
51#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070052#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080053#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"
ApurupaPattapu0c566872014-01-10 14:46:02 -080056#include "sound/asound.h"
57
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
59/* ToDo: Check and update a proper value in msec */
Alexy Joseph62babb92015-03-03 19:01:03 -080060#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
62
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +053063#define PROXY_OPEN_RETRY_COUNT 100
64#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapu0c566872014-01-10 14:46:02 -080065
Steve Kondikb045f472014-11-12 23:24:07 -080066#ifdef LOW_LATENCY_PRIMARY
67#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
68#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080069#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Steve Kondikb045f472014-11-12 23:24:07 -080070#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080071
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -070072static unsigned int configured_low_latency_capture_period_size =
73 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
74
Steve Kondik3abbbc82014-11-29 14:14:43 -080075/* This constant enables extended precision handling.
Steve Kondik3abbbc82014-11-29 14:14:43 -080076 */
77static const bool k_enable_extended_precision = true;
78
Eric Laurentb23d5282013-05-14 15:27:20 -070079struct pcm_config pcm_config_deep_buffer = {
80 .channels = 2,
81 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
82 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
83 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
84 .format = PCM_FORMAT_S16_LE,
85 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
86 .stop_threshold = INT_MAX,
87 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
88};
89
90struct pcm_config pcm_config_low_latency = {
91 .channels = 2,
92 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
93 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
94 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
95 .format = PCM_FORMAT_S16_LE,
96 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
97 .stop_threshold = INT_MAX,
98 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
99};
100
101struct pcm_config pcm_config_hdmi_multi = {
102 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
103 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
104 .period_size = HDMI_MULTI_PERIOD_SIZE,
105 .period_count = HDMI_MULTI_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = 0,
108 .stop_threshold = INT_MAX,
109 .avail_min = 0,
110};
111
112struct pcm_config pcm_config_audio_capture = {
113 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
115 .format = PCM_FORMAT_S16_LE,
116};
117
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530118#define AFE_PROXY_CHANNEL_COUNT 2
119#define AFE_PROXY_SAMPLING_RATE 48000
120
121#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
122#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
123
124struct pcm_config pcm_config_afe_proxy_playback = {
125 .channels = AFE_PROXY_CHANNEL_COUNT,
126 .rate = AFE_PROXY_SAMPLING_RATE,
127 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
128 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
131 .stop_threshold = INT_MAX,
132 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
133};
134
135#define AFE_PROXY_RECORD_PERIOD_SIZE 768
136#define AFE_PROXY_RECORD_PERIOD_COUNT 4
137
138struct pcm_config pcm_config_afe_proxy_record = {
139 .channels = AFE_PROXY_CHANNEL_COUNT,
140 .rate = AFE_PROXY_SAMPLING_RATE,
141 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
142 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
145 .stop_threshold = INT_MAX,
146 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
147};
148
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800149const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700150 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
151 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
152 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700153 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700154#ifdef MULTIPLE_OFFLOAD_ENABLED
155 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
156 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
157 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
158 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
159 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
160 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
161 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
162 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
163#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700164 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700165 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700167 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700168 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800169 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800170 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700171 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yinee733602014-04-03 17:47:22 -0700172
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700173 [USECASE_VOICE2_CALL] = "voice2-call",
174 [USECASE_VOLTE_CALL] = "volte-call",
175 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat111aeb32014-02-12 17:58:59 -0800176 [USECASE_VOWLAN_CALL] = "vowlan-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800177 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700178 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
179 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
180 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800181 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
182 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
183 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
184
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700185 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
186 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700187 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
188 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530189
190 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
191 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700192};
193
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700194static const audio_usecase_t offload_usecases[] = {
195 USECASE_AUDIO_PLAYBACK_OFFLOAD,
196#ifdef MULTIPLE_OFFLOAD_ENABLED
197 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
198 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
Steve Kondikac72feb2014-07-20 23:15:34 -0700199#ifndef PLATFORM_MSM8974
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700200 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
201 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
202 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
203 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
Steve Kondikac72feb2014-07-20 23:15:34 -0700204#endif
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700205 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
Steve Kondikac72feb2014-07-20 23:15:34 -0700206#ifndef PLATFORM_MSM8974
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700207 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
208#endif
Steve Kondikac72feb2014-07-20 23:15:34 -0700209#endif
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700210};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800211
212#define STRING_TO_ENUM(string) { #string, string }
213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800214struct string_to_enum {
215 const char *name;
216 uint32_t value;
217};
218
219static const struct string_to_enum out_channels_name_to_enum_table[] = {
220 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
221 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
222 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
223};
224
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700225static struct audio_device *adev = NULL;
226static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700227static unsigned int audio_device_ref_count;
228
Haynes Mathew George5191a852013-09-11 14:19:36 -0700229static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800230
Ethan Chen79c356c2015-06-07 12:26:14 -0700231static amplifier_device_t * get_amplifier_device(void)
232{
Dan Pasanen46f76f52015-08-10 19:55:39 -0500233 if (adev)
234 return adev->amp;
235
236 return NULL;
237}
238
239static int amplifier_open(void)
240{
Ethan Chen79c356c2015-06-07 12:26:14 -0700241 int rc;
242 amplifier_module_t *module;
243
Ethan Chen79c356c2015-06-07 12:26:14 -0700244 rc = hw_get_module(AMPLIFIER_HARDWARE_MODULE_ID,
245 (const hw_module_t **) &module);
246 if (rc) {
247 ALOGV("%s: Failed to obtain reference to amplifier module: %s\n",
248 __func__, strerror(-rc));
Dan Pasanen46f76f52015-08-10 19:55:39 -0500249 return -ENODEV;
Ethan Chen79c356c2015-06-07 12:26:14 -0700250 }
251
252 rc = amplifier_device_open((const hw_module_t *) module, &adev->amp);
253 if (rc) {
254 ALOGV("%s: Failed to open amplifier hardware device: %s\n",
255 __func__, strerror(-rc));
Ethan Chen79c356c2015-06-07 12:26:14 -0700256 return -ENODEV;
257 }
258
259 return 0;
260}
261
262static int amplifier_set_input_devices(uint32_t devices)
263{
264 amplifier_device_t *amp = get_amplifier_device();
265 if (amp && amp->set_input_devices)
266 return amp->set_input_devices(amp, devices);
267
268 return 0;
269}
270
271static int amplifier_set_output_devices(uint32_t devices)
272{
273 amplifier_device_t *amp = get_amplifier_device();
274 if (amp && amp->set_output_devices)
275 return amp->set_output_devices(amp, devices);
276
277 return 0;
278}
279
Ethan Chen6720ae62015-07-03 21:35:30 -0700280static int amplifier_enable_devices(uint32_t devices, bool enable)
281{
282 amplifier_device_t *amp = get_amplifier_device();
283 bool is_output = devices > SND_DEVICE_OUT_BEGIN &&
284 devices < SND_DEVICE_OUT_END;
285
286 if (amp && amp->enable_output_devices && is_output)
287 return amp->enable_output_devices(amp, devices, enable);
288
289 if (amp && amp->enable_input_devices && !is_output)
290 return amp->enable_input_devices(amp, devices, enable);
291
292 return 0;
293}
294
Ethan Chen79c356c2015-06-07 12:26:14 -0700295static int amplifier_set_mode(audio_mode_t mode)
296{
297 amplifier_device_t *amp = get_amplifier_device();
298 if (amp && amp->set_mode)
299 return amp->set_mode(amp, mode);
300
301 return 0;
302}
303
304static int amplifier_output_stream_start(struct audio_stream_out *stream,
305 bool offload)
306{
307 amplifier_device_t *amp = get_amplifier_device();
308 if (amp && amp->output_stream_start)
309 return amp->output_stream_start(amp, stream, offload);
310
311 return 0;
312}
313
314static int amplifier_input_stream_start(struct audio_stream_in *stream)
315{
316 amplifier_device_t *amp = get_amplifier_device();
317 if (amp && amp->input_stream_start)
318 return amp->input_stream_start(amp, stream);
319
320 return 0;
321}
322
323static int amplifier_output_stream_standby(struct audio_stream_out *stream)
324{
325 amplifier_device_t *amp = get_amplifier_device();
326 if (amp && amp->output_stream_standby)
327 return amp->output_stream_standby(amp, stream);
328
329 return 0;
330}
331
332static int amplifier_input_stream_standby(struct audio_stream_in *stream)
333{
334 amplifier_device_t *amp = get_amplifier_device();
335 if (amp && amp->input_stream_standby)
336 return amp->input_stream_standby(amp, stream);
337
338 return 0;
339}
340
341static int amplifier_close(void)
342{
343 amplifier_device_t *amp = get_amplifier_device();
344 if (amp)
345 amplifier_device_close(amp);
346
347 return 0;
348}
349
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800350static int check_and_set_gapless_mode(struct audio_device *adev) {
351
352
353 char value[PROPERTY_VALUE_MAX] = {0};
354 bool gapless_enabled = false;
355 const char *mixer_ctl_name = "Compress Gapless Playback";
356 struct mixer_ctl *ctl;
357
358 ALOGV("%s:", __func__);
359 property_get("audio.offload.gapless.enabled", value, NULL);
360 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
361
362 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
363 if (!ctl) {
364 ALOGE("%s: Could not get ctl for mixer cmd - %s",
365 __func__, mixer_ctl_name);
366 return -EINVAL;
367 }
368
369 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
370 ALOGE("%s: Could not set gapless mode %d",
371 __func__, gapless_enabled);
372 return -EINVAL;
373 }
374 return 0;
375}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700377static bool is_supported_format(audio_format_t format)
378{
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800379 switch (format) {
Steve Kondik3abbbc82014-11-29 14:14:43 -0800380 case AUDIO_FORMAT_MP3:
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800381 case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
382 case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700383#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik3abbbc82014-11-29 14:14:43 -0800384 case AUDIO_FORMAT_FLAC:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700385#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -0800386#ifdef WMA_OFFLOAD_ENABLED
387 case AUDIO_FORMAT_WMA:
388 case AUDIO_FORMAT_WMA_PRO:
389#endif
390#ifdef MP2_OFFLOAD_ENABLED
391 case AUDIO_FORMAT_MP2:
392#endif
393 case AUDIO_FORMAT_AAC_LC:
394 case AUDIO_FORMAT_AAC_HE_V1:
395 case AUDIO_FORMAT_AAC_HE_V2:
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530396 return true;
Steve Kondik3abbbc82014-11-29 14:14:43 -0800397
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800398 default:
399 return false;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530400 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700401 return false;
402}
403
404static int get_snd_codec_id(audio_format_t format)
405{
406 int id = 0;
407
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530408 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700409 case AUDIO_FORMAT_MP3:
410 id = SND_AUDIOCODEC_MP3;
411 break;
412 case AUDIO_FORMAT_AAC:
413 id = SND_AUDIOCODEC_AAC;
414 break;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530415 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapu0c566872014-01-10 14:46:02 -0800416 id = SND_AUDIOCODEC_PCM;
417 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700418#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800419 case AUDIO_FORMAT_FLAC:
420 id = SND_AUDIOCODEC_FLAC;
421 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700422#endif
Ethan Chenc856d972014-07-25 14:57:15 -0700423#ifdef WMA_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700424 case AUDIO_FORMAT_WMA:
425 id = SND_AUDIOCODEC_WMA;
426 break;
427 case AUDIO_FORMAT_WMA_PRO:
428 id = SND_AUDIOCODEC_WMA_PRO;
429 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700430#endif
431#ifdef MP2_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700432 case AUDIO_FORMAT_MP2:
433 id = SND_AUDIOCODEC_MP2;
434 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700435#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700436 default:
Mingming Yin90310102013-11-13 16:57:00 -0800437 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700438 }
439
440 return id;
441}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800442
Avinash Vaish8005dc82014-07-24 15:36:33 +0530443static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
444 struct audio_usecase *uc_info)
445{
446 struct listnode *node;
447 struct audio_usecase *usecase;
448
449 if (uc_info == NULL)
450 return -EINVAL;
451
452 /* Re-route all voice usecases on the shared backend other than the
453 specified usecase to new snd devices */
454 list_for_each(node, &adev->usecase_list) {
455 usecase = node_to_item(node, struct audio_usecase, list);
456 if ((usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) &&
457 (usecase != uc_info))
458 enable_audio_route(adev, usecase);
459 }
460 return 0;
461}
462
Venkata Narendra Kumar Guttac9e9e2c2014-07-09 16:29:28 +0530463int get_snd_card_state(struct audio_device *adev)
Naresh Tannirucef332d2014-06-04 18:17:56 +0530464{
465 int snd_scard_state;
466
467 if (!adev)
468 return SND_CARD_STATE_OFFLINE;
469
470 pthread_mutex_lock(&adev->snd_card_status.lock);
471 snd_scard_state = adev->snd_card_status.state;
472 pthread_mutex_unlock(&adev->snd_card_status.lock);
473
474 return snd_scard_state;
475}
476
477static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
478{
479 if (!adev)
480 return -ENOSYS;
481
482 pthread_mutex_lock(&adev->snd_card_status.lock);
483 adev->snd_card_status.state = snd_scard_state;
484 pthread_mutex_unlock(&adev->snd_card_status.lock);
485
486 return 0;
487}
488
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -0700489int pcm_ioctl(struct pcm *pcm, int request, ...)
490{
491 va_list ap;
492 void * arg;
493 int pcm_fd = *(int*)pcm;
494
495 va_start(ap, request);
496 arg = va_arg(ap, void *);
497 va_end(ap);
498
499 return ioctl(pcm_fd, request, arg);
500}
501
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700502int enable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700503 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800504{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700506 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800507
508 if (usecase == NULL)
509 return -EINVAL;
510
511 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
512
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800513 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700514 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800515 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700516 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800517
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -0800518#ifdef DS1_DOLBY_DAP_ENABLED
519 audio_extn_dolby_set_dmid(adev);
520 audio_extn_dolby_set_endpoint(adev);
521#endif
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800522 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700523 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700524 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
525 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800526 ALOGV("%s: exit", __func__);
527 return 0;
528}
529
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700530int disable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700531 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800532{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700533 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700534 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800535
536 if (usecase == NULL)
537 return -EINVAL;
538
539 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700540 if (usecase->type == PCM_CAPTURE)
541 snd_device = usecase->in_snd_device;
542 else
543 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800544 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700545 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700546 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
547 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800548 ALOGV("%s: exit", __func__);
549 return 0;
550}
551
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700552int enable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700553 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800554{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700555 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
556
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800557 if (snd_device < SND_DEVICE_MIN ||
558 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800559 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800560 return -EINVAL;
561 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700562
563 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700564
565 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
566 ALOGE("%s: Invalid sound device returned", __func__);
567 return -EINVAL;
568 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700569 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700570 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700571 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700572 return 0;
573 }
574
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700575 /* start usb playback thread */
576 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
577 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
578 audio_extn_usb_start_playback(adev);
579
580 /* start usb capture thread */
581 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
582 audio_extn_usb_start_capture(adev);
583
Tony Layher692f19a2015-01-03 13:16:45 -0500584 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
585 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700586 audio_extn_spkr_prot_is_enabled()) {
587 if (audio_extn_spkr_prot_start_processing(snd_device)) {
588 ALOGE("%s: spkr_start_processing failed", __func__);
589 return -EINVAL;
590 }
591 } else {
592 ALOGV("%s: snd_device(%d: %s)", __func__,
Steve Kondik0d268002015-10-16 01:57:18 -0700593 snd_device, device_name);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700594 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
595 adev->snd_dev_ref_cnt[snd_device]--;
596 return -EINVAL;
597 }
Steve Kondikad1a08a2015-11-11 16:26:25 +0100598 audio_extn_listen_update_status(snd_device,
599 LISTEN_EVENT_SND_DEVICE_BUSY);
Ethan Chen6720ae62015-07-03 21:35:30 -0700600 amplifier_enable_devices(snd_device, true);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700601 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800602 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800603 return 0;
604}
605
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700606int disable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700607 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800608{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700609 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
610
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800611 if (snd_device < SND_DEVICE_MIN ||
612 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800613 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800614 return -EINVAL;
615 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700616 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
617 ALOGE("%s: device ref cnt is already 0", __func__);
618 return -EINVAL;
619 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700620
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700621 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700622
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700623 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
624 ALOGE("%s: Invalid sound device returned", __func__);
625 return -EINVAL;
626 }
627
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700628 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700629 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700630 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800631 /* exit usb play back thread */
632 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
633 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
634 audio_extn_usb_stop_playback();
635
636 /* exit usb capture thread */
637 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Rajshekar Eashwarappa4dfa0752014-10-02 20:18:20 +0530638 audio_extn_usb_stop_capture();
Tony Layher692f19a2015-01-03 13:16:45 -0500639
640 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
641 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700642 audio_extn_spkr_prot_is_enabled()) {
643 audio_extn_spkr_prot_stop_processing();
Ethan Chen6720ae62015-07-03 21:35:30 -0700644 } else {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700645 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ethan Chen6720ae62015-07-03 21:35:30 -0700646 amplifier_enable_devices(snd_device, false);
647 }
Kiran Kandide144c82013-11-20 15:58:32 -0800648
Steve Kondikad1a08a2015-11-11 16:26:25 +0100649 audio_extn_listen_update_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800650 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700651 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700652
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800653 return 0;
654}
655
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700656static void check_usecases_codec_backend(struct audio_device *adev,
657 struct audio_usecase *uc_info,
658 snd_device_t snd_device)
659{
660 struct listnode *node;
661 struct audio_usecase *usecase;
662 bool switch_device[AUDIO_USECASE_MAX];
663 int i, num_uc_to_switch = 0;
664
665 /*
666 * This function is to make sure that all the usecases that are active on
667 * the hardware codec backend are always routed to any one device that is
668 * handled by the hardware codec.
669 * For example, if low-latency and deep-buffer usecases are currently active
670 * on speaker and out_set_parameters(headset) is received on low-latency
671 * output, then we have to make sure deep-buffer is also switched to headset,
672 * because of the limitation that both the devices cannot be enabled
673 * at the same time as they share the same backend.
674 */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800675 /*
676 * This call is to check if we need to force routing for a particular stream
677 * If there is a backend configuration change for the device when a
678 * new stream starts, then ADM needs to be closed and re-opened with the new
679 * configuraion. This call check if we need to re-route all the streams
680 * associated with the backend. Touch tone + 24 bit playback.
681 */
682 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
683
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700684 /* Disable all the usecases on the shared backend other than the
685 specified usecase */
686 for (i = 0; i < AUDIO_USECASE_MAX; i++)
687 switch_device[i] = false;
688
689 list_for_each(node, &adev->usecase_list) {
690 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800691 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700692 usecase != uc_info &&
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800693 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700694 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
695 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
696 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700697 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700698 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 switch_device[usecase->id] = true;
700 num_uc_to_switch++;
701 }
702 }
703
704 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700705 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700706
707 list_for_each(node, &adev->usecase_list) {
708 usecase = node_to_item(node, struct audio_usecase, list);
709 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700710 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700711 }
712 }
713
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700714 list_for_each(node, &adev->usecase_list) {
715 usecase = node_to_item(node, struct audio_usecase, list);
716 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700717 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700718 }
719 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700720
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 /* Re-route all the usecases on the shared backend other than the
722 specified usecase to new snd devices */
723 list_for_each(node, &adev->usecase_list) {
724 usecase = node_to_item(node, struct audio_usecase, list);
725 /* Update the out_snd_device only before enabling the audio route */
726 if (switch_device[usecase->id] ) {
727 usecase->out_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530728 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
729 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700730 }
731 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700732 }
733}
734
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700735static void check_and_route_capture_usecases(struct audio_device *adev,
736 struct audio_usecase *uc_info,
737 snd_device_t snd_device)
738{
739 struct listnode *node;
740 struct audio_usecase *usecase;
741 bool switch_device[AUDIO_USECASE_MAX];
742 int i, num_uc_to_switch = 0;
743
744 /*
745 * This function is to make sure that all the active capture usecases
746 * are always routed to the same input sound device.
747 * For example, if audio-record and voice-call usecases are currently
748 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
749 * is received for voice call then we have to make sure that audio-record
750 * usecase is also switched to earpiece i.e. voice-dmic-ef,
751 * because of the limitation that two devices cannot be enabled
752 * at the same time if they share the same backend.
753 */
754 for (i = 0; i < AUDIO_USECASE_MAX; i++)
755 switch_device[i] = false;
756
757 list_for_each(node, &adev->usecase_list) {
758 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800759 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700760 usecase != uc_info &&
Avinash Vaish44014792015-03-27 14:46:04 +0530761 usecase->in_snd_device != snd_device &&
762 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700763 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
764 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700765 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700766 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700767 switch_device[usecase->id] = true;
768 num_uc_to_switch++;
769 }
770 }
771
772 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700773 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774
775 list_for_each(node, &adev->usecase_list) {
776 usecase = node_to_item(node, struct audio_usecase, list);
777 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700778 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800779 }
780 }
781
782 list_for_each(node, &adev->usecase_list) {
783 usecase = node_to_item(node, struct audio_usecase, list);
784 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700785 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700786 }
787 }
788
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700789 /* Re-route all the usecases on the shared backend other than the
790 specified usecase to new snd devices */
791 list_for_each(node, &adev->usecase_list) {
792 usecase = node_to_item(node, struct audio_usecase, list);
793 /* Update the in_snd_device only before enabling the audio route */
794 if (switch_device[usecase->id] ) {
795 usecase->in_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530796 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
797 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700798 }
799 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700800 }
801}
802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800803/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700804static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800805{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700806 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700807 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800808
809 switch (channels) {
810 /*
811 * Do not handle stereo output in Multi-channel cases
812 * Stereo case is handled in normal playback path
813 */
814 case 6:
815 ALOGV("%s: HDMI supports 5.1", __func__);
816 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
817 break;
818 case 8:
819 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
820 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
821 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
822 break;
823 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700824 ALOGE("HDMI does not support multi channel playback");
825 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800826 break;
827 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700828 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800829}
830
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700831static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
832{
833 struct audio_usecase *usecase;
834 struct listnode *node;
835
836 list_for_each(node, &adev->usecase_list) {
837 usecase = node_to_item(node, struct audio_usecase, list);
838 if (usecase->type == VOICE_CALL) {
839 ALOGV("%s: usecase id %d", __func__, usecase->id);
840 return usecase->id;
841 }
842 }
843 return USECASE_INVALID;
844}
845
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700846struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700847 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700848{
849 struct audio_usecase *usecase;
850 struct listnode *node;
851
852 list_for_each(node, &adev->usecase_list) {
853 usecase = node_to_item(node, struct audio_usecase, list);
854 if (usecase->id == uc_id)
855 return usecase;
856 }
857 return NULL;
858}
859
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700860int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800861{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800862 snd_device_t out_snd_device = SND_DEVICE_NONE;
863 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700864 struct audio_usecase *usecase = NULL;
865 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800866 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800867 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800868 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800869 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700870 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800871
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700872 usecase = get_usecase_from_list(adev, uc_id);
873 if (usecase == NULL) {
874 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
875 return -EINVAL;
876 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800877
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800878 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800879 (usecase->type == VOIP_CALL) ||
880 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700881 out_snd_device = platform_get_output_snd_device(adev->platform,
882 usecase->stream.out->devices);
883 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700884 usecase->devices = usecase->stream.out->devices;
885 } else {
886 /*
887 * If the voice call is active, use the sound devices of voice call usecase
888 * so that it would not result any device switch. All the usecases will
889 * be switched to new device when select_devices() is called for voice call
890 * usecase. This is to avoid switching devices for voice call when
891 * check_usecases_codec_backend() is called below.
892 */
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -0700893 if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700894 vc_usecase = get_usecase_from_list(adev,
895 get_voice_usecase_id_from_list(adev));
Mingming Yin6c23f382014-08-14 00:00:51 -0700896 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
897 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700898 in_snd_device = vc_usecase->in_snd_device;
899 out_snd_device = vc_usecase->out_snd_device;
900 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800901 } else if (voice_extn_compress_voip_is_active(adev)) {
902 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin6c23f382014-08-14 00:00:51 -0700903 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish6a4c3372014-06-25 12:20:37 +0530904 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin6c23f382014-08-14 00:00:51 -0700905 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800906 in_snd_device = voip_usecase->in_snd_device;
907 out_snd_device = voip_usecase->out_snd_device;
908 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800909 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800910 hfp_ucid = audio_extn_hfp_get_usecase();
911 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin6c23f382014-08-14 00:00:51 -0700912 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800913 in_snd_device = hfp_usecase->in_snd_device;
914 out_snd_device = hfp_usecase->out_snd_device;
915 }
Vimal Puthanveed8fa9eab2014-01-07 16:47:47 -0800916 } else if (audio_extn_hfp_is_active(adev)) {
917 hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
918 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
919 in_snd_device = hfp_usecase->in_snd_device;
920 out_snd_device = hfp_usecase->out_snd_device;
921 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700922 }
923 if (usecase->type == PCM_PLAYBACK) {
924 usecase->devices = usecase->stream.out->devices;
925 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700926 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700927 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700928 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700929 if (usecase->stream.out == adev->primary_output &&
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530930 adev->active_input ) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700931 select_devices(adev, adev->active_input->usecase);
932 }
933 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700934 } else if (usecase->type == PCM_CAPTURE) {
935 usecase->devices = usecase->stream.in->device;
936 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700937 if (in_snd_device == SND_DEVICE_NONE) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530938 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530939 if ((adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION || (adev->mode == AUDIO_MODE_IN_COMMUNICATION && adev->active_input->source == AUDIO_SOURCE_MIC)) &&
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700940 adev->primary_output && !adev->primary_output->standby) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530941 out_device = adev->primary_output->devices;
942 } else if(usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
943 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700944 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530945 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700946 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700947 }
948 }
949
950 if (out_snd_device == usecase->out_snd_device &&
951 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800952 return 0;
953 }
954
sangwoobc677242013-08-08 16:53:43 +0900955 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700956 out_snd_device, platform_get_snd_device_name(out_snd_device),
957 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800959 /*
960 * Limitation: While in call, to do a device switch we need to disable
961 * and enable both RX and TX devices though one of them is same as current
962 * device.
963 */
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800964 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700965 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800966 }
967
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 /* Disable current sound devices */
969 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700970 disable_audio_route(adev, usecase);
971 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800972 }
973
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700974 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700975 disable_audio_route(adev, usecase);
976 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800977 }
978
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 /* Enable new sound devices */
980 if (out_snd_device != SND_DEVICE_NONE) {
981 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
982 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700983 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800984 }
985
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700986 if (in_snd_device != SND_DEVICE_NONE) {
987 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700988 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700989 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990
Avinash Vaish8005dc82014-07-24 15:36:33 +0530991 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700992 status = platform_switch_voice_call_device_post(adev->platform,
993 out_snd_device,
994 in_snd_device);
Avinash Vaish8005dc82014-07-24 15:36:33 +0530995 enable_audio_route_for_voice_usecases(adev, usecase);
996 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800997
sangwoo170731f2013-06-08 15:36:36 +0900998 usecase->in_snd_device = in_snd_device;
999 usecase->out_snd_device = out_snd_device;
1000
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001001 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001002
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301003 /* Rely on amplifier_set_devices to distinguish between in/out devices */
Ethan Chen79c356c2015-06-07 12:26:14 -07001004 amplifier_set_input_devices(in_snd_device);
1005 amplifier_set_output_devices(out_snd_device);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301006
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001007 /* Applicable only on the targets that has external modem.
1008 * Enable device command should be sent to modem only after
1009 * enabling voice call mixer controls
1010 */
1011 if (usecase->type == VOICE_CALL)
1012 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1013 out_snd_device,
1014 in_snd_device);
1015
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301016 ALOGD("%s: done",__func__);
1017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001018 return status;
1019}
1020
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001021static int stop_input_stream(struct stream_in *in)
1022{
1023 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001024 struct audio_usecase *uc_info;
1025 struct audio_device *adev = in->dev;
1026
Eric Laurentc8400632013-02-14 19:04:54 -08001027 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028
Eric Laurent994a6932013-07-17 11:51:42 -07001029 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001030 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 uc_info = get_usecase_from_list(adev, in->usecase);
1032 if (uc_info == NULL) {
1033 ALOGE("%s: Could not find the usecase (%d) in the list",
1034 __func__, in->usecase);
1035 return -EINVAL;
1036 }
1037
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001038 /* Close in-call recording streams */
1039 voice_check_and_stop_incall_rec_usecase(adev, in);
1040
Eric Laurent150dbfe2013-02-27 14:31:02 -08001041 /* 1. Disable stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001042 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001043
1044 /* 2. Disable the tx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001045 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001046
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001047 list_remove(&uc_info->list);
1048 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001049
Eric Laurent994a6932013-07-17 11:51:42 -07001050 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051 return ret;
1052}
1053
1054int start_input_stream(struct stream_in *in)
1055{
1056 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001057 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058 struct audio_usecase *uc_info;
1059 struct audio_device *adev = in->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301060 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001061
Ramjee Singh240ac652015-07-31 16:12:29 +05301062 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1063 if (get_usecase_from_list(adev, usecase) == NULL)
1064 in->usecase = usecase;
1065
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301066 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1067 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001068
Naresh Tannirucef332d2014-06-04 18:17:56 +05301069 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
1070 ALOGE("%s: sound card is not active/SSR returning error ", __func__);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301071 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301072 goto error_config;
1073 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301074
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001075 /* Check if source matches incall recording usecase criteria */
1076 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1077 if (ret)
1078 goto error_config;
1079 else
1080 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1081
Ramjee Singh240ac652015-07-31 16:12:29 +05301082 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1083 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1084 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1085 goto error_config;
1086 }
1087
Eric Laurentb23d5282013-05-14 15:27:20 -07001088 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001089 if (in->pcm_device_id < 0) {
1090 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1091 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001092 ret = -EINVAL;
1093 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001094 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001095
1096 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001098
1099 if (!uc_info) {
1100 ret = -ENOMEM;
1101 goto error_config;
1102 }
1103
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104 uc_info->id = in->usecase;
1105 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001106 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001107 uc_info->devices = in->device;
1108 uc_info->in_snd_device = SND_DEVICE_NONE;
1109 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001110
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001111 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001113
Eric Laurentc8400632013-02-14 19:04:54 -08001114 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301115 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1116
1117 unsigned int flags = PCM_IN;
1118 unsigned int pcm_open_retry_entry_count = 0;
1119
1120 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1121 flags |= PCM_MMAP | PCM_NOIRQ;
1122 pcm_open_retry_entry_count = PROXY_OPEN_RETRY_COUNT;
1123 }
1124
1125 while(1) {
1126 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1127 flags, &in->config);
1128 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1129 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1130 if (in->pcm != NULL) {
1131 pcm_close(in->pcm);
1132 in->pcm = NULL;
1133 }
1134 if (pcm_open_retry_entry_count-- == 0) {
1135 ret = -EIO;
1136 goto error_open;
1137 }
1138 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1139 continue;
1140 }
1141 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301143
Eric Laurent994a6932013-07-17 11:51:42 -07001144 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001145 return ret;
1146
1147error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001148 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001149
1150error_config:
1151 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001153
1154 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155}
1156
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001157/* must be called with out->lock locked */
1158static int send_offload_cmd_l(struct stream_out* out, int command)
1159{
1160 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1161
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001162 if (!cmd) {
1163 ALOGE("failed to allocate mem for command 0x%x", command);
1164 return -ENOMEM;
1165 }
1166
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001167 ALOGVV("%s %d", __func__, command);
1168
1169 cmd->cmd = command;
1170 list_add_tail(&out->offload_cmd_list, &cmd->node);
1171 pthread_cond_signal(&out->offload_cond);
1172 return 0;
1173}
1174
1175/* must be called iwth out->lock locked */
1176static void stop_compressed_output_l(struct stream_out *out)
1177{
1178 out->offload_state = OFFLOAD_STATE_IDLE;
1179 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001180 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001181 if (out->compr != NULL) {
1182 compress_stop(out->compr);
1183 while (out->offload_thread_blocked) {
1184 pthread_cond_wait(&out->cond, &out->lock);
1185 }
1186 }
1187}
1188
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001189bool is_offload_usecase(audio_usecase_t uc_id)
1190{
1191 unsigned int i;
1192 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1193 if (uc_id == offload_usecases[i])
1194 return true;
1195 }
1196 return false;
1197}
1198
1199static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1200{
1201 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1202 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1203 char value[PROPERTY_VALUE_MAX] = {0};
1204
1205 property_get("audio.offload.multiple.enabled", value, NULL);
1206 if (!(atoi(value) || !strncmp("true", value, 4)))
1207 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1208
1209 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1210 for (i = 0; i < num_usecase; i++) {
1211 if (!(adev->offload_usecases_state & (0x1<<i))) {
1212 adev->offload_usecases_state |= 0x1 << i;
1213 ret = offload_usecases[i];
1214 break;
1215 }
1216 }
1217 ALOGV("%s: offload usecase is %d", __func__, ret);
1218 return ret;
1219}
1220
1221static void free_offload_usecase(struct audio_device *adev,
1222 audio_usecase_t uc_id)
1223{
1224 unsigned int i;
1225 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1226 if (offload_usecases[i] == uc_id) {
1227 adev->offload_usecases_state &= ~(0x1<<i);
1228 break;
1229 }
1230 }
1231 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1232}
1233
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001234static void *offload_thread_loop(void *context)
1235{
1236 struct stream_out *out = (struct stream_out *) context;
1237 struct listnode *item;
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001238 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001239
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001240 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1241 set_sched_policy(0, SP_FOREGROUND);
1242 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1243
1244 ALOGV("%s", __func__);
1245 pthread_mutex_lock(&out->lock);
1246 for (;;) {
1247 struct offload_cmd *cmd = NULL;
1248 stream_callback_event_t event;
1249 bool send_callback = false;
1250
1251 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1252 __func__, list_empty(&out->offload_cmd_list),
1253 out->offload_state);
1254 if (list_empty(&out->offload_cmd_list)) {
1255 ALOGV("%s SLEEPING", __func__);
1256 pthread_cond_wait(&out->offload_cond, &out->lock);
1257 ALOGV("%s RUNNING", __func__);
1258 continue;
1259 }
1260
1261 item = list_head(&out->offload_cmd_list);
1262 cmd = node_to_item(item, struct offload_cmd, node);
1263 list_remove(item);
1264
1265 ALOGVV("%s STATE %d CMD %d out->compr %p",
1266 __func__, out->offload_state, cmd->cmd, out->compr);
1267
1268 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1269 free(cmd);
1270 break;
1271 }
1272
1273 if (out->compr == NULL) {
1274 ALOGE("%s: Compress handle is NULL", __func__);
1275 pthread_cond_signal(&out->cond);
1276 continue;
1277 }
1278 out->offload_thread_blocked = true;
1279 pthread_mutex_unlock(&out->lock);
1280 send_callback = false;
1281 switch(cmd->cmd) {
1282 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Steve Kondik05c17962015-02-25 00:55:50 -08001283 ALOGV("copl(%x):calling compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001284 compress_wait(out->compr, -1);
Steve Kondik05c17962015-02-25 00:55:50 -08001285 ALOGV("copl(%x):out of compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001286 send_callback = true;
1287 event = STREAM_CBK_EVENT_WRITE_READY;
1288 break;
1289 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001290 ret = compress_next_track(out->compr);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301291 if(ret == 0) {
Steve Kondik05c17962015-02-25 00:55:50 -08001292 ALOGV("copl(%p):calling compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301293 ret = compress_partial_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001294 ALOGV("copl(%p):out of compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301295 if (ret < 0)
1296 ret = -errno;
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301297 }
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301298 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001299 compress_drain(out->compr);
1300 else
1301 ALOGE("%s: Next track returned error %d",__func__, ret);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301302
1303 if (ret != -ENETRESET) {
1304 send_callback = true;
1305 event = STREAM_CBK_EVENT_DRAIN_READY;
1306
1307 /* Resend the metadata for next iteration */
1308 out->send_new_metadata = 1;
1309 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1310 } else
1311 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001312 break;
1313 case OFFLOAD_CMD_DRAIN:
Steve Kondik05c17962015-02-25 00:55:50 -08001314 ALOGV("copl(%x):calling compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001315 compress_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001316 ALOGV("copl(%x):out of compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001317 send_callback = true;
1318 event = STREAM_CBK_EVENT_DRAIN_READY;
1319 break;
1320 default:
1321 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1322 break;
1323 }
1324 pthread_mutex_lock(&out->lock);
1325 out->offload_thread_blocked = false;
1326 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001327 if (send_callback) {
Ravi Kumar Alamanda3d316172014-12-02 19:21:51 -08001328 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001329 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001330 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001331 free(cmd);
1332 }
1333
1334 pthread_cond_signal(&out->cond);
1335 while (!list_empty(&out->offload_cmd_list)) {
1336 item = list_head(&out->offload_cmd_list);
1337 list_remove(item);
1338 free(node_to_item(item, struct offload_cmd, node));
1339 }
1340 pthread_mutex_unlock(&out->lock);
1341
1342 return NULL;
1343}
1344
1345static int create_offload_callback_thread(struct stream_out *out)
1346{
1347 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1348 list_init(&out->offload_cmd_list);
1349 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1350 offload_thread_loop, out);
1351 return 0;
1352}
1353
1354static int destroy_offload_callback_thread(struct stream_out *out)
1355{
1356 pthread_mutex_lock(&out->lock);
1357 stop_compressed_output_l(out);
1358 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1359
1360 pthread_mutex_unlock(&out->lock);
1361 pthread_join(out->offload_thread, (void **) NULL);
1362 pthread_cond_destroy(&out->offload_cond);
1363
1364 return 0;
1365}
1366
Eric Laurent07eeafd2013-10-06 12:52:49 -07001367static bool allow_hdmi_channel_config(struct audio_device *adev)
1368{
1369 struct listnode *node;
1370 struct audio_usecase *usecase;
1371 bool ret = true;
1372
1373 list_for_each(node, &adev->usecase_list) {
1374 usecase = node_to_item(node, struct audio_usecase, list);
1375 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1376 /*
1377 * If voice call is already existing, do not proceed further to avoid
1378 * disabling/enabling both RX and TX devices, CSD calls, etc.
1379 * Once the voice call done, the HDMI channels can be configured to
1380 * max channels of remaining use cases.
1381 */
1382 if (usecase->id == USECASE_VOICE_CALL) {
1383 ALOGD("%s: voice call is active, no change in HDMI channels",
1384 __func__);
1385 ret = false;
1386 break;
1387 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1388 ALOGD("%s: multi channel playback is active, "
1389 "no change in HDMI channels", __func__);
1390 ret = false;
1391 break;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001392 } else if (is_offload_usecase(usecase->id) &&
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301393 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin3ed162b2014-02-24 17:56:01 -08001394 ALOGD("%s: multi-channel(%x) compress offload playback is active, "
1395 "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
1396 ret = false;
1397 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001398 }
1399 }
1400 }
1401 return ret;
1402}
1403
1404static int check_and_set_hdmi_channels(struct audio_device *adev,
1405 unsigned int channels)
1406{
1407 struct listnode *node;
1408 struct audio_usecase *usecase;
1409
1410 /* Check if change in HDMI channel config is allowed */
1411 if (!allow_hdmi_channel_config(adev))
1412 return 0;
1413
1414 if (channels == adev->cur_hdmi_channels) {
Mingming Yin10fef6a2013-11-26 17:17:01 -08001415 ALOGD("%s: Requested channels are same as current channels(%d)", __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001416 return 0;
1417 }
1418
1419 platform_set_hdmi_channels(adev->platform, channels);
1420 adev->cur_hdmi_channels = channels;
1421
1422 /*
1423 * Deroute all the playback streams routed to HDMI so that
1424 * the back end is deactivated. Note that backend will not
1425 * be deactivated if any one stream is connected to it.
1426 */
1427 list_for_each(node, &adev->usecase_list) {
1428 usecase = node_to_item(node, struct audio_usecase, list);
1429 if (usecase->type == PCM_PLAYBACK &&
1430 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001431 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001432 }
1433 }
1434
1435 /*
1436 * Enable all the streams disabled above. Now the HDMI backend
1437 * will be activated with new channel configuration
1438 */
1439 list_for_each(node, &adev->usecase_list) {
1440 usecase = node_to_item(node, struct audio_usecase, list);
1441 if (usecase->type == PCM_PLAYBACK &&
1442 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001443 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001444 }
1445 }
1446
1447 return 0;
1448}
1449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001450static int stop_output_stream(struct stream_out *out)
1451{
1452 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001453 struct audio_usecase *uc_info;
1454 struct audio_device *adev = out->dev;
1455
Eric Laurent994a6932013-07-17 11:51:42 -07001456 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001457 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001458 uc_info = get_usecase_from_list(adev, out->usecase);
1459 if (uc_info == NULL) {
1460 ALOGE("%s: Could not find the usecase (%d) in the list",
1461 __func__, out->usecase);
1462 return -EINVAL;
1463 }
1464
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001465 if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001466 if (adev->visualizer_stop_output != NULL)
1467 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1468 if (adev->offload_effects_stop_output != NULL)
1469 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1470 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001471
Eric Laurent150dbfe2013-02-27 14:31:02 -08001472 /* 1. Get and set stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001473 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001474
1475 /* 2. Disable the rx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001476 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001478 list_remove(&uc_info->list);
1479 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001480
Eric Laurentda46bfb2014-08-25 22:39:29 -05001481 audio_extn_extspk_update(adev->extspk);
1482
Eric Laurent07eeafd2013-10-06 12:52:49 -07001483 /* Must be called after removing the usecase from list */
1484 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1485 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1486
Eric Laurent994a6932013-07-17 11:51:42 -07001487 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488 return ret;
1489}
1490
1491int start_output_stream(struct stream_out *out)
1492{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001493 int ret = 0;
Mingming Yin6c344432014-05-01 15:37:31 -07001494 int sink_channels = 0;
1495 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001496 struct audio_usecase *uc_info;
1497 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301498 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001500 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1501 ret = -EINVAL;
1502 goto error_config;
1503 }
1504
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301505 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1506 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1507 out->devices);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301508
Naresh Tannirucef332d2014-06-04 18:17:56 +05301509 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301510 ALOGE("%s: sound card is not active/SSR returning error", __func__);
1511 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301512 goto error_config;
1513 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301514
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301515 ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
1516 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001517 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518 if (out->pcm_device_id < 0) {
1519 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1520 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001521 ret = -EINVAL;
1522 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001523 }
1524
1525 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001526
1527 if (!uc_info) {
1528 ret = -ENOMEM;
1529 goto error_config;
1530 }
1531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 uc_info->id = out->usecase;
1533 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001534 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535 uc_info->devices = out->devices;
1536 uc_info->in_snd_device = SND_DEVICE_NONE;
1537 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001538
Eric Laurent07eeafd2013-10-06 12:52:49 -07001539 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001540 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Mingming Yin6c344432014-05-01 15:37:31 -07001541 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1542 if (!strncmp("true", prop_value, 4)) {
1543 sink_channels = platform_edid_get_max_channels(out->dev->platform);
1544 ALOGD("%s: set HDMI channel count[%d] based on sink capability", __func__, sink_channels);
1545 check_and_set_hdmi_channels(adev, sink_channels);
1546 } else {
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001547 if (is_offload_usecase(out->usecase))
Mingming Yin6c344432014-05-01 15:37:31 -07001548 check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in);
1549 else
1550 check_and_set_hdmi_channels(adev, out->config.channels);
1551 }
Mingming Yin10fef6a2013-11-26 17:17:01 -08001552 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001553
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001554 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001555
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001556 select_devices(adev, out->usecase);
1557
Eric Laurentda46bfb2014-08-25 22:39:29 -05001558 audio_extn_extspk_update(adev->extspk);
1559
Steve Kondik3abbbc82014-11-29 14:14:43 -08001560 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1561 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
1562
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001563 if (!is_offload_usecase(out->usecase)) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301564 unsigned int flags = PCM_OUT;
1565 unsigned int pcm_open_retry_count = 0;
1566 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1567 flags |= PCM_MMAP | PCM_NOIRQ;
1568 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1569 } else
1570 flags |= PCM_MONOTONIC;
1571
1572 while (1) {
1573 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1574 flags, &out->config);
1575 if (out->pcm && !pcm_is_ready(out->pcm)) {
1576 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1577 if (out->pcm != NULL) {
1578 pcm_close(out->pcm);
1579 out->pcm = NULL;
1580 }
1581 if (pcm_open_retry_count-- == 0) {
1582 ret = -EIO;
1583 goto error_open;
1584 }
1585 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1586 continue;
1587 }
1588 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001589 }
1590 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001591 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001592 out->compr = compress_open(adev->snd_card,
1593 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001594 COMPRESS_IN, &out->compr_config);
1595 if (out->compr && !is_compress_ready(out->compr)) {
1596 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1597 compress_close(out->compr);
1598 out->compr = NULL;
1599 ret = -EIO;
1600 goto error_open;
1601 }
1602 if (out->offload_callback)
1603 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001604
Fred Oh1483d8a2015-03-04 18:42:34 -08001605 /* Since small bufs uses blocking writes, a write will be blocked
1606 for the default max poll time (20s) in the event of an SSR.
1607 Reduce the poll time to observe and deal with SSR faster.
1608 */
1609 if (out->use_small_bufs) {
1610 compress_set_max_poll_wait(out->compr, 1000);
1611 }
1612
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08001613#ifdef DS1_DOLBY_DDP_ENABLED
1614 if (audio_extn_is_dolby_format(out->format))
1615 audio_extn_dolby_send_ddp_endp_params(adev);
1616#endif
1617
Eric Laurentc4aef752013-09-12 17:45:53 -07001618 if (adev->visualizer_start_output != NULL)
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001619 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1620 if (adev->offload_effects_start_output != NULL)
1621 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 }
Eric Laurent994a6932013-07-17 11:51:42 -07001623 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001624 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001625error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001626 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001627error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001628 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629}
1630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631static int check_input_parameters(uint32_t sample_rate,
1632 audio_format_t format,
1633 int channel_count)
1634{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001635 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001636
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001637 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001638 !voice_extn_compress_voip_is_format_supported(format) &&
1639 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001640
1641 switch (channel_count) {
1642 case 1:
1643 case 2:
1644 case 6:
1645 break;
1646 default:
1647 ret = -EINVAL;
1648 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001649
1650 switch (sample_rate) {
1651 case 8000:
1652 case 11025:
1653 case 12000:
1654 case 16000:
1655 case 22050:
1656 case 24000:
1657 case 32000:
1658 case 44100:
1659 case 48000:
1660 break;
1661 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001662 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001663 }
1664
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001665 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666}
1667
1668static size_t get_input_buffer_size(uint32_t sample_rate,
1669 audio_format_t format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001670 int channel_count,
1671 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672{
1673 size_t size = 0;
1674
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001675 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1676 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001678 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001679 if (is_low_latency)
1680 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001681 /* ToDo: should use frame_size computed based on the format and
1682 channel_count here. */
1683 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001685 /* make sure the size is multiple of 32 bytes
1686 * At 48 kHz mono 16-bit PCM:
1687 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1688 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1689 */
1690 size += 0x1f;
1691 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001692
1693 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694}
1695
1696static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1697{
1698 struct stream_out *out = (struct stream_out *)stream;
1699
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001700 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701}
1702
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301703static int out_set_sample_rate(struct audio_stream *stream __unused,
1704 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705{
1706 return -ENOSYS;
1707}
1708
1709static size_t out_get_buffer_size(const struct audio_stream *stream)
1710{
1711 struct stream_out *out = (struct stream_out *)stream;
1712
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001713 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001714 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001715 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1716 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001717
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301718 return out->config.period_size *
1719 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720}
1721
1722static uint32_t out_get_channels(const struct audio_stream *stream)
1723{
1724 struct stream_out *out = (struct stream_out *)stream;
1725
1726 return out->channel_mask;
1727}
1728
1729static audio_format_t out_get_format(const struct audio_stream *stream)
1730{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001731 struct stream_out *out = (struct stream_out *)stream;
1732
1733 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734}
1735
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301736static int out_set_format(struct audio_stream *stream __unused,
1737 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738{
1739 return -ENOSYS;
1740}
1741
1742static int out_standby(struct audio_stream *stream)
1743{
1744 struct stream_out *out = (struct stream_out *)stream;
1745 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301747 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1748 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001749 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1750 /* Ignore standby in case of voip call because the voip output
1751 * stream is closed in adev_close_output_stream()
1752 */
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301753 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001754 return 0;
1755 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001757 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001758 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001759 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07001760
1761 amplifier_output_stream_standby((struct audio_stream_out *) stream);
1762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763 out->standby = true;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001764 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765 if (out->pcm) {
1766 pcm_close(out->pcm);
1767 out->pcm = NULL;
1768 }
1769 } else {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301770 ALOGD("copl(%x):standby", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001771 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001772 out->gapless_mdata.encoder_delay = 0;
1773 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001774 if (out->compr != NULL) {
1775 compress_close(out->compr);
1776 out->compr = NULL;
1777 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001778 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001779 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001780 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001781 }
1782 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001783 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001784 return 0;
1785}
1786
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301787static int out_dump(const struct audio_stream *stream __unused,
1788 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789{
1790 return 0;
1791}
1792
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001793static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1794{
1795 int ret = 0;
1796 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001797 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001798 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001799 tmp_mdata.encoder_delay = 0;
1800 tmp_mdata.encoder_padding = 0;
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001801
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001802 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001803 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001804 return -EINVAL;
1805 }
1806
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001807 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1808 if (ret >= 0) {
1809 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1810 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1811 ALOGV("ADTS format is set in offload mode");
1812 }
1813 out->send_new_metadata = 1;
1814 }
1815
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001816#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001817 if (out->format == AUDIO_FORMAT_FLAC) {
1818 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1819 if (ret >= 0) {
1820 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1821 out->send_new_metadata = 1;
1822 }
1823 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1824 if (ret >= 0) {
1825 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1826 out->send_new_metadata = 1;
1827 }
1828 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1829 if (ret >= 0) {
1830 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1831 out->send_new_metadata = 1;
1832 }
1833 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1834 if (ret >= 0) {
1835 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1836 out->send_new_metadata = 1;
1837 }
1838 }
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001839#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001840
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001841 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1842 if(ret >= 0)
1843 is_meta_data_params = true;
1844 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1845 if(ret >= 0 )
1846 is_meta_data_params = true;
1847 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1848 if(ret >= 0 )
1849 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001850 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1851 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001852 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001853 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001854 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001855 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1856 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001857 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001858 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001859 }
1860
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001861 if(!is_meta_data_params) {
1862 ALOGV("%s: Not gapless meta data params", __func__);
1863 return 0;
1864 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001865 out->gapless_mdata = tmp_mdata;
1866 out->send_new_metadata = 1;
1867 ALOGV("%s new encoder delay %u and padding %u", __func__,
1868 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1869
Steve Kondikba3b35d2014-07-18 01:49:48 -07001870 if(out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
1871 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
1872 if (ret >= 0) {
1873 out->compr_config.codec->format = atoi(value);
1874 }
1875 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
1876 if (ret >= 0) {
1877 out->compr_config.codec->options.wma.super_block_align = atoi(value);
1878 }
1879 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
1880 if (ret >= 0) {
1881 out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
1882 }
1883 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
1884 if (ret >= 0) {
1885 out->compr_config.codec->options.wma.channelmask = atoi(value);
1886 }
1887 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
1888 if (ret >= 0) {
1889 out->compr_config.codec->options.wma.encodeopt = atoi(value);
1890 }
1891 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
1892 if (ret >= 0) {
1893 out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
1894 }
1895 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
1896 if (ret >= 0) {
1897 out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
1898 }
1899 ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
1900 out->compr_config.codec->format,
1901 out->compr_config.codec->options.wma.super_block_align,
1902 out->compr_config.codec->options.wma.bits_per_sample,
1903 out->compr_config.codec->options.wma.channelmask,
1904 out->compr_config.codec->options.wma.encodeopt,
1905 out->compr_config.codec->options.wma.encodeopt1,
1906 out->compr_config.codec->options.wma.encodeopt2);
1907 }
1908
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001909 return 0;
1910}
1911
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301912static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1913{
1914 return out == adev->primary_output || out == adev->voice_tx_output;
1915}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1918{
1919 struct stream_out *out = (struct stream_out *)stream;
1920 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001921 struct audio_usecase *usecase;
1922 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 struct str_parms *parms;
1924 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001925 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001926 bool select_new_device = false;
Steve Kondik3abbbc82014-11-29 14:14:43 -08001927 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001928
sangwoobc677242013-08-08 16:53:43 +09001929 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001930 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001931 parms = str_parms_create_str(kvpairs);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001932 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1933 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001934 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001936 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001937
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001938 /*
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301939 * When HDMI cable is unplugged/usb hs is disconnected the
1940 * music playback is paused and the policy manager sends routing=0
1941 * But the audioflingercontinues to write data until standby time
1942 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001943 * Avoid this by routing audio to speaker until standby.
1944 */
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301945 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
Steve Kondikeadb6c82014-09-03 18:40:06 -07001946 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
1947 out->devices == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001948 val == AUDIO_DEVICE_NONE) {
1949 val = AUDIO_DEVICE_OUT_SPEAKER;
1950 }
1951
1952 /*
1953 * select_devices() call below switches all the usecases on the same
1954 * backend to the new device. Refer to check_usecases_codec_backend() in
1955 * the select_devices(). But how do we undo this?
1956 *
1957 * For example, music playback is active on headset (deep-buffer usecase)
1958 * and if we go to ringtones and select a ringtone, low-latency usecase
1959 * will be started on headset+speaker. As we can't enable headset+speaker
1960 * and headset devices at the same time, select_devices() switches the music
1961 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1962 * So when the ringtone playback is completed, how do we undo the same?
1963 *
1964 * We are relying on the out_set_parameters() call on deep-buffer output,
1965 * once the ringtone playback is ended.
1966 * NOTE: We should not check if the current devices are same as new devices.
1967 * Because select_devices() must be called to switch back the music
1968 * playback to headset.
1969 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001970 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001971 out->devices = val;
1972
1973 if (!out->standby)
1974 select_devices(adev, out->usecase);
1975
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001976 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301977 output_drives_call(adev, out)) {
1978 adev->current_call_output = out;
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001979 if (!adev->voice.in_call)
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301980 ret = voice_start_call(adev);
1981 else
1982 voice_update_devices_for_all_voice_usecases(adev);
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001983 }
1984 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001985
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001986 if ((adev->mode == AUDIO_MODE_NORMAL) &&
1987 adev->voice.in_call &&
1988 output_drives_call(adev, out)) {
1989 ret = voice_stop_call(adev);
1990 adev->current_call_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001991 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001992
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001994 pthread_mutex_unlock(&out->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05001995
1996 /*handles device and call state changes*/
1997 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001999
2000 if (out == adev->primary_output) {
2001 pthread_mutex_lock(&adev->lock);
2002 audio_extn_set_parameters(adev, parms);
2003 pthread_mutex_unlock(&adev->lock);
2004 }
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002005 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002006 pthread_mutex_lock(&out->lock);
Steve Kondikba3b35d2014-07-18 01:49:48 -07002007 ret = parse_compress_metadata(out, parms);
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002008 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002009 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002011 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002012 ALOGV("%s: exit: code(%d)", __func__, status);
2013 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014}
2015
2016static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2017{
2018 struct stream_out *out = (struct stream_out *)stream;
2019 struct str_parms *query = str_parms_create_str(keys);
2020 char *str;
2021 char value[256];
2022 struct str_parms *reply = str_parms_create();
2023 size_t i, j;
2024 int ret;
2025 bool first = true;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002026
2027 if (!query || !reply) {
2028 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2029 return NULL;
2030 }
2031
Eric Laurent994a6932013-07-17 11:51:42 -07002032 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2034 if (ret >= 0) {
2035 value[0] = '\0';
2036 i = 0;
2037 while (out->supported_channel_masks[i] != 0) {
2038 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2039 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2040 if (!first) {
2041 strcat(value, "|");
2042 }
2043 strcat(value, out_channels_name_to_enum_table[j].name);
2044 first = false;
2045 break;
2046 }
2047 }
2048 i++;
2049 }
2050 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2051 str = str_parms_to_str(reply);
2052 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002053 voice_extn_out_get_parameters(out, query, reply);
2054 str = str_parms_to_str(reply);
2055 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella2e032352014-01-29 12:52:19 -08002056 free(str);
2057 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002058 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059 }
2060 str_parms_destroy(query);
2061 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002062 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002063 return str;
2064}
2065
2066static uint32_t out_get_latency(const struct audio_stream_out *stream)
2067{
2068 struct stream_out *out = (struct stream_out *)stream;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002069 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002071 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002072 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002073 } else {
2074 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002075 (out->config.rate);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002076 }
2077
Anish Kumar1a0594f2014-12-09 04:01:39 +05302078 ALOGV("%s: Latency %d", __func__, latency);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002079 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002080}
2081
2082static int out_set_volume(struct audio_stream_out *stream, float left,
2083 float right)
2084{
Eric Laurenta9024de2013-04-04 09:19:12 -07002085 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002086 int volume[2];
2087
Eric Laurenta9024de2013-04-04 09:19:12 -07002088 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2089 /* only take left channel into account: the API is for stereo anyway */
2090 out->muted = (left == 0.0f);
2091 return 0;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002092 } else if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002093 char mixer_ctl_name[128];
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002094 struct audio_device *adev = out->dev;
2095 struct mixer_ctl *ctl;
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002096 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2097 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002098
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002099 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2100 "Compress Playback %d Volume", pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002101 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2102 if (!ctl) {
2103 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2104 __func__, mixer_ctl_name);
2105 return -EINVAL;
2106 }
2107 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2108 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2109 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2110 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002111 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 return -ENOSYS;
2114}
2115
2116static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2117 size_t bytes)
2118{
2119 struct stream_out *out = (struct stream_out *)stream;
2120 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302121 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002122 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002123
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124 pthread_mutex_lock(&out->lock);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302125
Naresh Tannirucef332d2014-06-04 18:17:56 +05302126 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
2127 if (out->pcm) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302128 ALOGD(" %s: sound card is not active/SSR state", __func__);
2129 ret= -ENETRESET;
2130 goto exit;
Alexy Joseph55204352014-10-06 12:15:01 -07002131 } else if (is_offload_usecase(out->usecase)) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302132 //during SSR for compress usecase we should return error to flinger
2133 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2134 pthread_mutex_unlock(&out->lock);
2135 return -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302136 }
2137 }
2138
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002139 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002140 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002141 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002142 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2143 ret = voice_extn_compress_voip_start_output_stream(out);
2144 else
2145 ret = start_output_stream(out);
Ethan Chen79c356c2015-06-07 12:26:14 -07002146
2147 if (ret == 0)
2148 amplifier_output_stream_start(stream,
2149 is_offload_usecase(out->usecase));
2150
Eric Laurent150dbfe2013-02-27 14:31:02 -08002151 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002152 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002153 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002154 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002155 goto exit;
2156 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002159 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002160 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002161 if (out->send_new_metadata) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302162 ALOGD("copl(%x):send new gapless metadata", (unsigned int)out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002163 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2164 out->send_new_metadata = 0;
2165 }
2166
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002167 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302168 if (ret < 0)
2169 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002171 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302172 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002173 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302174 } else if (-ENETRESET == ret) {
2175 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2176 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2177 pthread_mutex_unlock(&out->lock);
2178 out_standby(&out->stream.common);
2179 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002180 }
Naresh Tannirucef332d2014-06-04 18:17:56 +05302181 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002182 compress_start(out->compr);
2183 out->playback_started = 1;
2184 out->offload_state = OFFLOAD_STATE_PLAYING;
2185 }
2186 pthread_mutex_unlock(&out->lock);
2187 return ret;
2188 } else {
2189 if (out->pcm) {
2190 if (out->muted)
2191 memset((void *)buffer, 0, bytes);
2192 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302193 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2194 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2195 else
2196 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302197 if (ret < 0)
2198 ret = -errno;
2199 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002200 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002201 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002202 }
2203
2204exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302205 /* ToDo: There may be a corner case when SSR happens back to back during
2206 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302207 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302208 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302209 }
2210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 pthread_mutex_unlock(&out->lock);
2212
2213 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002214 if (out->pcm)
2215 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302216 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302217 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302218 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302219 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302220 out->standby = true;
2221 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222 out_standby(&out->stream.common);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002223 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
2224 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002225 }
2226 return bytes;
2227}
2228
2229static int out_get_render_position(const struct audio_stream_out *stream,
2230 uint32_t *dsp_frames)
2231{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 struct stream_out *out = (struct stream_out *)stream;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002233 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
2234 ssize_t ret = 0;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002235 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002236 pthread_mutex_lock(&out->lock);
2237 if (out->compr != NULL) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302238 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 &out->sample_rate);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302240 if (ret < 0)
2241 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002242 ALOGVV("%s rendered frames %d sample_rate %d",
2243 __func__, *dsp_frames, out->sample_rate);
2244 }
2245 pthread_mutex_unlock(&out->lock);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302246 if (-ENETRESET == ret) {
2247 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2248 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2249 return -EINVAL;
2250 } else if(ret < 0) {
Steve Kondik81506242014-07-21 16:12:57 -07002251 if (out->compr == NULL) {
2252 return 0;
2253 }
2254 ALOGE(" ERROR: Unable to get time stamp from compress driver ret=%d", ret);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302255 return -EINVAL;
2256 } else {
2257 return 0;
2258 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002259 } else
2260 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002261}
2262
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302263static int out_add_audio_effect(const struct audio_stream *stream __unused,
2264 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002265{
2266 return 0;
2267}
2268
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302269static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2270 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002271{
2272 return 0;
2273}
2274
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302275static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2276 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277{
2278 return -EINVAL;
2279}
2280
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002281static int out_get_presentation_position(const struct audio_stream_out *stream,
2282 uint64_t *frames, struct timespec *timestamp)
2283{
2284 struct stream_out *out = (struct stream_out *)stream;
2285 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002286 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002287
2288 pthread_mutex_lock(&out->lock);
2289
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002290 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002291 if (out->compr != NULL) {
2292 compress_get_tstamp(out->compr, &dsp_frames,
2293 &out->sample_rate);
2294 ALOGVV("%s rendered frames %ld sample_rate %d",
2295 __func__, dsp_frames, out->sample_rate);
2296 *frames = dsp_frames;
2297 ret = 0;
2298 /* this is the best we can do */
2299 clock_gettime(CLOCK_MONOTONIC, timestamp);
2300 }
2301 } else {
2302 if (out->pcm) {
2303 size_t avail;
2304 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2305 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002306 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002307 // This adjustment accounts for buffering after app processor.
2308 // It is based on estimated DSP latency per use case, rather than exact.
2309 signed_frames -=
2310 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2311
Eric Laurent949a0892013-09-20 09:20:13 -07002312 // It would be unusual for this value to be negative, but check just in case ...
2313 if (signed_frames >= 0) {
2314 *frames = signed_frames;
2315 ret = 0;
2316 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002317 }
2318 }
2319 }
2320
2321 pthread_mutex_unlock(&out->lock);
2322
2323 return ret;
2324}
2325
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002326static int out_set_callback(struct audio_stream_out *stream,
2327 stream_callback_t callback, void *cookie)
2328{
2329 struct stream_out *out = (struct stream_out *)stream;
2330
2331 ALOGV("%s", __func__);
2332 pthread_mutex_lock(&out->lock);
2333 out->offload_callback = callback;
2334 out->offload_cookie = cookie;
2335 pthread_mutex_unlock(&out->lock);
2336 return 0;
2337}
2338
2339static int out_pause(struct audio_stream_out* stream)
2340{
2341 struct stream_out *out = (struct stream_out *)stream;
2342 int status = -ENOSYS;
2343 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002344 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302345 ALOGD("copl(%x):pause compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002346 pthread_mutex_lock(&out->lock);
2347 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302348 struct audio_device *adev = out->dev;
2349 int snd_scard_state = get_snd_card_state(adev);
2350
2351 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2352 status = compress_pause(out->compr);
2353
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002354 out->offload_state = OFFLOAD_STATE_PAUSED;
2355 }
2356 pthread_mutex_unlock(&out->lock);
2357 }
2358 return status;
2359}
2360
2361static int out_resume(struct audio_stream_out* stream)
2362{
2363 struct stream_out *out = (struct stream_out *)stream;
2364 int status = -ENOSYS;
2365 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002366 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302367 ALOGD("copl(%x):resume compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002368 status = 0;
2369 pthread_mutex_lock(&out->lock);
2370 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302371 struct audio_device *adev = out->dev;
2372 int snd_scard_state = get_snd_card_state(adev);
2373
2374 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2375 status = compress_resume(out->compr);
2376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002377 out->offload_state = OFFLOAD_STATE_PLAYING;
2378 }
2379 pthread_mutex_unlock(&out->lock);
2380 }
2381 return status;
2382}
2383
2384static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2385{
2386 struct stream_out *out = (struct stream_out *)stream;
2387 int status = -ENOSYS;
2388 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002389 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002390 pthread_mutex_lock(&out->lock);
2391 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2392 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2393 else
2394 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2395 pthread_mutex_unlock(&out->lock);
2396 }
2397 return status;
2398}
2399
2400static int out_flush(struct audio_stream_out* stream)
2401{
2402 struct stream_out *out = (struct stream_out *)stream;
2403 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002404 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302405 ALOGD("copl(%x):calling compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002406 pthread_mutex_lock(&out->lock);
2407 stop_compressed_output_l(out);
2408 pthread_mutex_unlock(&out->lock);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302409 ALOGD("copl(%x):out of compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002410 return 0;
2411 }
2412 return -ENOSYS;
2413}
2414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415/** audio_stream_in implementation **/
2416static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2417{
2418 struct stream_in *in = (struct stream_in *)stream;
2419
2420 return in->config.rate;
2421}
2422
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302423static int in_set_sample_rate(struct audio_stream *stream __unused,
2424 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425{
2426 return -ENOSYS;
2427}
2428
2429static size_t in_get_buffer_size(const struct audio_stream *stream)
2430{
2431 struct stream_in *in = (struct stream_in *)stream;
2432
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002433 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2434 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002435 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2436 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002437
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302438 return in->config.period_size *
Steve Kondik3abbbc82014-11-29 14:14:43 -08002439 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440}
2441
2442static uint32_t in_get_channels(const struct audio_stream *stream)
2443{
2444 struct stream_in *in = (struct stream_in *)stream;
2445
2446 return in->channel_mask;
2447}
2448
2449static audio_format_t in_get_format(const struct audio_stream *stream)
2450{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002451 struct stream_in *in = (struct stream_in *)stream;
2452
2453 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002454}
2455
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302456static int in_set_format(struct audio_stream *stream __unused,
2457 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458{
2459 return -ENOSYS;
2460}
2461
2462static int in_standby(struct audio_stream *stream)
2463{
2464 struct stream_in *in = (struct stream_in *)stream;
2465 struct audio_device *adev = in->dev;
2466 int status = 0;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302467 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2468 stream, in->usecase, use_case_table[in->usecase]);
2469
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002470
2471 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2472 /* Ignore standby in case of voip call because the voip input
2473 * stream is closed in adev_close_input_stream()
2474 */
2475 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2476 return status;
2477 }
2478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 pthread_mutex_lock(&in->lock);
2480 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002481 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07002482
2483 amplifier_input_stream_standby((struct audio_stream_in *) stream);
2484
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002486 if (in->pcm) {
2487 pcm_close(in->pcm);
2488 in->pcm = NULL;
2489 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002490 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002491 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 }
2493 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002494 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495 return status;
2496}
2497
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302498static int in_dump(const struct audio_stream *stream __unused,
2499 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002500{
2501 return 0;
2502}
2503
2504static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2505{
2506 struct stream_in *in = (struct stream_in *)stream;
2507 struct audio_device *adev = in->dev;
2508 struct str_parms *parms;
2509 char *str;
2510 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002511 int ret = 0, val = 0, err;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002512 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302514 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002515 parms = str_parms_create_str(kvpairs);
2516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002518 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002519
2520 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2521 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 val = atoi(value);
2523 /* no audio source uses val == 0 */
2524 if ((in->source != val) && (val != 0)) {
2525 in->source = val;
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002526 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2527 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2528 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2529 (in->config.rate == 8000 || in->config.rate == 16000) &&
Steve Kondikb6ab1fa2015-02-06 16:55:26 -08002530 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002531 err = voice_extn_compress_voip_open_input_stream(in);
2532 if (err != 0) {
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002533 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002534 __func__, err);
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002535 }
2536 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002537 }
2538 }
2539
Steve Kondik3abbbc82014-11-29 14:14:43 -08002540 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2541
2542 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002543 val = atoi(value);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302544 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545 in->device = val;
2546 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002547 if (!in->standby)
Steve Kondik3abbbc82014-11-29 14:14:43 -08002548 status = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002549 }
2550 }
2551
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002552done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002553 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002554 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555
2556 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002557 ALOGV("%s: exit: status(%d)", __func__, status);
2558 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002559}
2560
2561static char* in_get_parameters(const struct audio_stream *stream,
2562 const char *keys)
2563{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002564 struct stream_in *in = (struct stream_in *)stream;
2565 struct str_parms *query = str_parms_create_str(keys);
2566 char *str;
2567 char value[256];
2568 struct str_parms *reply = str_parms_create();
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002569
2570 if (!query || !reply) {
2571 ALOGE("in_get_parameters: failed to create query or reply");
2572 return NULL;
2573 }
2574
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002575 ALOGV("%s: enter: keys - %s", __func__, keys);
2576
2577 voice_extn_in_get_parameters(in, query, reply);
2578
2579 str = str_parms_to_str(reply);
2580 str_parms_destroy(query);
2581 str_parms_destroy(reply);
2582
2583 ALOGV("%s: exit: returns - %s", __func__, str);
2584 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002585}
2586
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302587static int in_set_gain(struct audio_stream_in *stream __unused,
2588 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589{
2590 return 0;
2591}
2592
2593static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2594 size_t bytes)
2595{
2596 struct stream_in *in = (struct stream_in *)stream;
2597 struct audio_device *adev = in->dev;
2598 int i, ret = -1;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302599 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 pthread_mutex_lock(&in->lock);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302602
2603 if (in->pcm) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302604 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302605 ALOGD(" %s: sound card is not active/SSR state", __func__);
2606 ret= -ENETRESET;
2607 goto exit;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302608 }
2609 }
2610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002612 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002613 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2614 ret = voice_extn_compress_voip_start_input_stream(in);
2615 else
2616 ret = start_input_stream(in);
Ethan Chen79c356c2015-06-07 12:26:14 -07002617
2618 if (ret == 0)
2619 amplifier_input_stream_start(stream);
2620
Eric Laurent150dbfe2013-02-27 14:31:02 -08002621 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623 goto exit;
2624 }
2625 in->standby = 0;
2626 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627
2628 if (in->pcm) {
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302629 if (audio_extn_ssr_get_enabled() &&
2630 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002631 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002632 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2633 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302634 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2635 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002636 else
2637 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302638 if (ret < 0)
2639 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640 }
2641
2642 /*
2643 * Instead of writing zeroes here, we could trust the hardware
2644 * to always provide zeroes when muted.
2645 */
Pavan Chikkala6c183fd2014-12-04 10:48:28 +05302646 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2647 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002648 memset(buffer, 0, bytes);
2649
2650exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302651 /* ToDo: There may be a corner case when SSR happens back to back during
2652 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302653 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302654 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302655 memset(buffer, 0, bytes);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302656 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 pthread_mutex_unlock(&in->lock);
2658
2659 if (ret != 0) {
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302660 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302661 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302662 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302663 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302664 in->standby = true;
2665 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 in_standby(&in->stream.common);
2667 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002668 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
2669 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 }
2671 return bytes;
2672}
2673
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302674static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675{
2676 return 0;
2677}
2678
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002679static int add_remove_audio_effect(const struct audio_stream *stream,
2680 effect_handle_t effect,
2681 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002683 struct stream_in *in = (struct stream_in *)stream;
2684 int status = 0;
2685 effect_descriptor_t desc;
2686
2687 status = (*effect)->get_descriptor(effect, &desc);
2688 if (status != 0)
2689 return status;
2690
2691 pthread_mutex_lock(&in->lock);
2692 pthread_mutex_lock(&in->dev->lock);
2693 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2694 in->enable_aec != enable &&
2695 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2696 in->enable_aec = enable;
2697 if (!in->standby)
2698 select_devices(in->dev, in->usecase);
2699 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002700 if (in->enable_ns != enable &&
2701 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2702 in->enable_ns = enable;
2703 if (!in->standby)
2704 select_devices(in->dev, in->usecase);
2705 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002706 pthread_mutex_unlock(&in->dev->lock);
2707 pthread_mutex_unlock(&in->lock);
2708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002709 return 0;
2710}
2711
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002712static int in_add_audio_effect(const struct audio_stream *stream,
2713 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002714{
Eric Laurent994a6932013-07-17 11:51:42 -07002715 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002716 return add_remove_audio_effect(stream, effect, true);
2717}
2718
2719static int in_remove_audio_effect(const struct audio_stream *stream,
2720 effect_handle_t effect)
2721{
Eric Laurent994a6932013-07-17 11:51:42 -07002722 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002723 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002724}
2725
2726static int adev_open_output_stream(struct audio_hw_device *dev,
2727 audio_io_handle_t handle,
2728 audio_devices_t devices,
2729 audio_output_flags_t flags,
2730 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302731 struct audio_stream_out **stream_out,
2732 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002733{
2734 struct audio_device *adev = (struct audio_device *)dev;
2735 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002736 int i, ret = 0;
Steve Kondik5a447012014-12-02 16:04:20 -08002737 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739 *stream_out = NULL;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302740
2741 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2742 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2743 ALOGE(" sound card is not active rejecting compress output open request");
2744 return -EINVAL;
2745 }
2746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2748
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302749 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2750 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2751 devices, flags, &out->stream);
2752
2753
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002754 if (!out) {
2755 return -ENOMEM;
2756 }
2757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 if (devices == AUDIO_DEVICE_NONE)
2759 devices = AUDIO_DEVICE_OUT_SPEAKER;
2760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761 out->flags = flags;
2762 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002763 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002764 out->format = config->format;
2765 out->sample_rate = config->sample_rate;
2766 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2767 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002768 out->handle = handle;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002769 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002770 out->non_blocking = 0;
2771 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772
2773 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002774 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
Mingming Yinee733602014-04-03 17:47:22 -07002775 (
2776#ifdef AFE_PROXY_ENABLED
2777 out->devices & AUDIO_DEVICE_OUT_PROXY ||
2778#endif
2779 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002780
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002781 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002782 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2783 ret = read_hdmi_channel_masks(out);
2784
Mingming Yinee733602014-04-03 17:47:22 -07002785#ifdef AFE_PROXY_ENABLED
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002786 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2787 ret = audio_extn_read_afe_proxy_channel_masks(out);
Mingming Yinee733602014-04-03 17:47:22 -07002788#endif
2789
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002790 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002791 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002792 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002793
2794 if (config->sample_rate == 0)
2795 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2796 if (config->channel_mask == 0)
2797 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2798
2799 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002800 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2802 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803 out->config.rate = config->sample_rate;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302804 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Mingming Yinee733602014-04-03 17:47:22 -07002806#ifdef COMPRESS_VOIP_ENABLED
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002807 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2808 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002809 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002810 ret = voice_extn_compress_voip_open_output_stream(out);
2811 if (ret != 0) {
2812 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2813 __func__, ret);
2814 goto error_open;
2815 }
Mingming Yinee733602014-04-03 17:47:22 -07002816#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002817 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302818 ALOGD("%s: copl(%x): sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
2819 __func__, (unsigned int)out, config->sample_rate, config->channel_mask, devices, flags);
2820
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2822 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2823 ALOGE("%s: Unsupported Offload information", __func__);
2824 ret = -EINVAL;
2825 goto error_open;
2826 }
Mingming Yin90310102013-11-13 16:57:00 -08002827 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002828 !audio_extn_is_dolby_format(config->offload_info.format)) {
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002829 ALOGE("%s: Unsupported offload audio format %x", __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002830 ret = -EINVAL;
2831 goto error_open;
2832 }
2833
2834 out->compr_config.codec = (struct snd_codec *)
2835 calloc(1, sizeof(struct snd_codec));
2836
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002837 if (!out->compr_config.codec) {
2838 ret = -ENOMEM;
2839 goto error_open;
2840 }
2841
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002842 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002843 if (config->offload_info.channel_mask)
2844 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002845 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002846 out->channel_mask = config->channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002847 config->offload_info.channel_mask = config->channel_mask;
2848 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 out->format = config->offload_info.format;
2850 out->sample_rate = config->offload_info.sample_rate;
2851
2852 out->stream.set_callback = out_set_callback;
2853 out->stream.pause = out_pause;
2854 out->stream.resume = out_resume;
2855 out->stream.drain = out_drain;
2856 out->stream.flush = out_flush;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002857 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002858
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002859 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002860 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002861 audio_extn_dolby_get_snd_codec_id(adev, out,
2862 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002863 else
2864 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002865 get_snd_codec_id(config->offload_info.format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002866
ApurupaPattapu0c566872014-01-10 14:46:02 -08002867 if (audio_is_offload_pcm(config->offload_info.format)) {
2868 out->compr_config.fragment_size =
2869 platform_get_pcm_offload_buffer_size(&config->offload_info);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002870 } else {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002871 out->compr_config.fragment_size =
2872 platform_get_compress_offload_buffer_size(&config->offload_info);
2873 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002874 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0043e152014-10-23 14:42:59 -07002875#ifdef NEW_SAMPLE_RATE_ENABLED
2876 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
2877#else
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 out->compr_config.codec->sample_rate =
2879 compress_get_alsa_rate(config->offload_info.sample_rate);
Eric Laurent0043e152014-10-23 14:42:59 -07002880#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 out->compr_config.codec->bit_rate =
2882 config->offload_info.bit_rate;
2883 out->compr_config.codec->ch_in =
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302884 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002886 out->bit_width = config->offload_info.bit_width;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002887
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002888 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
Steve Kondik37454012014-11-23 19:54:21 -08002889 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002890 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2891 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002892
Steve Kondik3abbbc82014-11-29 14:14:43 -08002893 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002894 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002895
Steve Kondik3abbbc82014-11-29 14:14:43 -08002896 if (out->bit_width == 24)
2897 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002898
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002899#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik37454012014-11-23 19:54:21 -08002900 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
2901 out->compr_config.codec->options.flac_dec.sample_size = config->offload_info.bit_width;
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002902#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002903
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002904 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2905 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002906
Mingming Yind48310a2015-06-10 16:28:10 -07002907 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002908 //this flag is set from framework only if its for PCM formats
2909 //no need to check for PCM format again
2910 out->non_blocking = 0;
2911 out->use_small_bufs = true;
2912 ALOGI("Keep write blocking for small buff: non_blockling %d",
2913 out->non_blocking);
2914 }
2915
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002916 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002917 out->offload_state = OFFLOAD_STATE_IDLE;
2918 out->playback_started = 0;
2919
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002920 create_offload_callback_thread(out);
2921 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2922 __func__, config->offload_info.version,
2923 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002924 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -08002925 check_and_set_gapless_mode(adev);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002926
Mingming Yinee733602014-04-03 17:47:22 -07002927#ifdef INCALL_MUSIC_ENABLED
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002928 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2929 ret = voice_check_and_set_incall_music_usecase(adev, out);
2930 if (ret != 0) {
2931 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2932 __func__, ret);
2933 goto error_open;
2934 }
Mingming Yinee733602014-04-03 17:47:22 -07002935#endif
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302936 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2937 if (config->sample_rate == 0)
2938 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2939 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2940 config->sample_rate != 8000) {
2941 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2942 ret = -EINVAL;
2943 goto error_open;
2944 }
2945 out->sample_rate = config->sample_rate;
2946 out->config.rate = config->sample_rate;
2947 if (config->format == AUDIO_FORMAT_DEFAULT)
2948 config->format = AUDIO_FORMAT_PCM_16_BIT;
2949 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2950 config->format = AUDIO_FORMAT_PCM_16_BIT;
2951 ret = -EINVAL;
2952 goto error_open;
2953 }
2954 out->format = config->format;
2955 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2956 out->config = pcm_config_afe_proxy_playback;
2957 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002958 } else {
Steve Kondik3abbbc82014-11-29 14:14:43 -08002959#ifndef LOW_LATENCY_PRIMARY
2960 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
2961 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2962 out->config = pcm_config_low_latency;
Steve Kondikb045f472014-11-12 23:24:07 -08002963#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -08002964#ifdef LOW_LATENCY_PRIMARY
2965 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2966 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2967 out->config = pcm_config_deep_buffer;
2968#endif
2969 } else {
2970 /* primary path is the default path selected if no other outputs are available/suitable */
2971 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
2972#ifdef LOW_LATENCY_PRIMARY
2973 out->config = pcm_config_low_latency;
2974#else
2975 out->config = pcm_config_deep_buffer;
2976#endif
2977 }
2978 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2979 if (k_enable_extended_precision
2980 && pcm_params_format_test(adev->use_case_table[out->usecase],
2981 pcm_format_from_audio_format(config->format))) {
2982 out->config.format = pcm_format_from_audio_format(config->format);
2983 /* out->format already set to config->format */
2984 } else {
2985 /* deny the externally proposed config format
2986 * and use the one specified in audio_hw layer configuration.
2987 * Note: out->format is returned by out->stream.common.get_format()
2988 * and is used to set config->format in the code several lines below.
2989 */
Steve Kondik5a447012014-12-02 16:04:20 -08002990 ALOGW("Audio format %x is not available on this output", out->format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002991 out->format = audio_format_from_pcm_format(out->config.format);
2992 }
2993 }
2994
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002995 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002996 }
2997
Steve Kondik5a447012014-12-02 16:04:20 -08002998 ALOGV("%s flags %x, format %x, sample_rate %d, out->bit_width %d",
2999 __func__, flags, out->format, out->sample_rate, out->bit_width);
3000
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003001 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
Steve Kondik3abbbc82014-11-29 14:14:43 -08003002 flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003003 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003004 if(adev->primary_output == NULL)
3005 adev->primary_output = out;
3006 else {
3007 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003008 ret = -EEXIST;
3009 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003010 }
3011 }
3012
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003013 /* Check if this usecase is already existing */
3014 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella0d06c8e2014-04-17 20:00:41 -07003015 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3016 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003017 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003019 ret = -EEXIST;
3020 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003021 }
3022 pthread_mutex_unlock(&adev->lock);
3023
3024 out->stream.common.get_sample_rate = out_get_sample_rate;
3025 out->stream.common.set_sample_rate = out_set_sample_rate;
3026 out->stream.common.get_buffer_size = out_get_buffer_size;
3027 out->stream.common.get_channels = out_get_channels;
3028 out->stream.common.get_format = out_get_format;
3029 out->stream.common.set_format = out_set_format;
3030 out->stream.common.standby = out_standby;
3031 out->stream.common.dump = out_dump;
3032 out->stream.common.set_parameters = out_set_parameters;
3033 out->stream.common.get_parameters = out_get_parameters;
3034 out->stream.common.add_audio_effect = out_add_audio_effect;
3035 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3036 out->stream.get_latency = out_get_latency;
3037 out->stream.set_volume = out_set_volume;
3038 out->stream.write = out_write;
3039 out->stream.get_render_position = out_get_render_position;
3040 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003041 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003044 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003045 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003046
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303047 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3048 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 config->format = out->stream.common.get_format(&out->stream.common);
3051 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3052 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3053
3054 *stream_out = &out->stream;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303055 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3056 use_case_table[out->usecase]);
Eric Laurent994a6932013-07-17 11:51:42 -07003057 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003059
3060error_open:
3061 free(out);
3062 *stream_out = NULL;
3063 ALOGD("%s: exit: ret %d", __func__, ret);
3064 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065}
3066
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303067static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 struct audio_stream_out *stream)
3069{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003070 struct stream_out *out = (struct stream_out *)stream;
3071 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003072 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303074 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3075
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003076 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303077 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003078 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303079 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003080 if(ret != 0)
3081 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3082 __func__, ret);
3083 }
3084 else
3085 out_standby(&stream->common);
3086
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003087 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003088 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003089 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090 if (out->compr_config.codec != NULL)
3091 free(out->compr_config.codec);
3092 }
3093 pthread_cond_destroy(&out->cond);
3094 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003096 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003097}
3098
Alexy Joseph55204352014-10-06 12:15:01 -07003099static void close_compress_sessions(struct audio_device *adev)
3100{
3101 struct stream_out *out = NULL;
3102 struct listnode *node = NULL;
3103 struct listnode *tmp = NULL;
3104 struct audio_usecase *usecase = NULL;
3105 pthread_mutex_lock(&adev->lock);
3106 list_for_each_safe(node, tmp, &adev->usecase_list) {
3107 usecase = node_to_item(node, struct audio_usecase, list);
3108 if (is_offload_usecase(usecase->id)) {
3109 if (usecase && usecase->stream.out) {
3110 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3111 out = usecase->stream.out;
3112 pthread_mutex_unlock(&adev->lock);
3113 out_standby(&out->stream.common);
3114 pthread_mutex_lock(&adev->lock);
3115 }
3116 }
3117 }
3118 pthread_mutex_unlock(&adev->lock);
3119}
3120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003121static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3122{
3123 struct audio_device *adev = (struct audio_device *)dev;
3124 struct str_parms *parms;
3125 char *str;
3126 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003127 int val;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303128 int ret;
3129 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003131 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003132 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303134 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3135 if (ret >= 0) {
3136 char *snd_card_status = value+2;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303137 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05303138 struct listnode *node;
3139 struct audio_usecase *usecase;
3140
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303141 ALOGD("Received sound card OFFLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303142 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3143
Alexy Joseph55204352014-10-06 12:15:01 -07003144 //close compress sessions on OFFLINE status
3145 close_compress_sessions(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303146 } else if (strstr(snd_card_status, "ONLINE")) {
3147 ALOGD("Received sound card ONLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303148 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303149 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303150 }
3151
3152 pthread_mutex_lock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303153 status = voice_set_parameters(adev, parms);
3154 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003155 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303157 status = platform_set_parameters(adev->platform, parms);
3158 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003159 goto done;
3160
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303161 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3162 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163 /* When set to false, HAL should disable EC and NS
3164 * But it is currently not supported.
3165 */
3166 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3167 adev->bluetooth_nrec = true;
3168 else
3169 adev->bluetooth_nrec = false;
3170 }
3171
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303172 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3173 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003174 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3175 adev->screen_off = false;
3176 else
3177 adev->screen_off = true;
3178 }
3179
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303180 ret = str_parms_get_int(parms, "rotation", &val);
3181 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003182 bool reverse_speakers = false;
3183 switch(val) {
3184 // FIXME: note that the code below assumes that the speakers are in the correct placement
3185 // relative to the user when the device is rotated 90deg from its default rotation. This
3186 // assumption is device-specific, not platform-specific like this code.
3187 case 270:
3188 reverse_speakers = true;
3189 break;
3190 case 0:
3191 case 90:
3192 case 180:
3193 break;
3194 default:
3195 ALOGE("%s: unexpected rotation of %d", __func__, val);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303196 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003197 }
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303198 if (status == 0) {
3199 if (adev->speaker_lr_swap != reverse_speakers) {
3200 adev->speaker_lr_swap = reverse_speakers;
3201 // only update the selected device if there is active pcm playback
3202 struct audio_usecase *usecase;
3203 struct listnode *node;
3204 list_for_each(node, &adev->usecase_list) {
3205 usecase = node_to_item(node, struct audio_usecase, list);
3206 if (usecase->type == PCM_PLAYBACK) {
Steve Kondik3abbbc82014-11-29 14:14:43 -08003207 status = select_devices(adev, usecase->id);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303208 break;
3209 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003210 }
3211 }
3212 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003213 }
3214
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003215 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003216
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003217done:
3218 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003219 pthread_mutex_unlock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303220 ALOGV("%s: exit with code(%d)", __func__, status);
3221 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003222}
3223
3224static char* adev_get_parameters(const struct audio_hw_device *dev,
3225 const char *keys)
3226{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003227 struct audio_device *adev = (struct audio_device *)dev;
3228 struct str_parms *reply = str_parms_create();
3229 struct str_parms *query = str_parms_create_str(keys);
3230 char *str;
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303231 char value[256] = {0};
3232 int ret = 0;
3233
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003234 if (!query || !reply) {
3235 ALOGE("adev_get_parameters: failed to create query or reply");
3236 return NULL;
3237 }
3238
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303239 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
3240 sizeof(value));
3241 if (ret >=0) {
3242 int val = 1;
3243 pthread_mutex_lock(&adev->snd_card_status.lock);
3244 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3245 val = 0;
3246 pthread_mutex_unlock(&adev->snd_card_status.lock);
3247 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, val);
3248 goto exit;
3249 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003250
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003251 pthread_mutex_lock(&adev->lock);
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303252
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003253 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003254 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003255 platform_get_parameters(adev->platform, query, reply);
Naresh Tannirucef332d2014-06-04 18:17:56 +05303256 pthread_mutex_unlock(&adev->lock);
3257
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303258exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003259 str = str_parms_to_str(reply);
3260 str_parms_destroy(query);
3261 str_parms_destroy(reply);
3262
3263 ALOGV("%s: exit: returns - %s", __func__, str);
3264 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003265}
3266
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303267static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268{
3269 return 0;
3270}
3271
3272static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3273{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003274 int ret;
3275 struct audio_device *adev = (struct audio_device *)dev;
Eric Laurent321b96d2014-09-10 13:21:01 -05003276
3277 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3278
Haynes Mathew George5191a852013-09-11 14:19:36 -07003279 pthread_mutex_lock(&adev->lock);
3280 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003281 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003282 pthread_mutex_unlock(&adev->lock);
3283 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003284}
3285
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303286static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3287 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003288{
3289 return -ENOSYS;
3290}
3291
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303292static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3293 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003294{
3295 return -ENOSYS;
3296}
3297
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303298static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3299 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003300{
3301 return -ENOSYS;
3302}
3303
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303304static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3305 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306{
3307 return -ENOSYS;
3308}
3309
3310static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3311{
3312 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313 pthread_mutex_lock(&adev->lock);
3314 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003315 ALOGD("%s mode %d\n", __func__, mode);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303316 if (amplifier_set_mode(mode) != 0)
3317 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003318 adev->mode = mode;
3319 }
3320 pthread_mutex_unlock(&adev->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003321
3322 audio_extn_extspk_set_mode(adev->extspk, mode);
3323
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003324 return 0;
3325}
3326
3327static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3328{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003329 int ret;
3330
3331 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003332 ALOGD("%s state %d\n", __func__, state);
Shreyas Nagasandra Chandrasekhar9781c6c2014-12-01 05:49:35 -08003333 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003334 pthread_mutex_unlock(&adev->lock);
3335
3336 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337}
3338
3339static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3340{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003341 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003342 return 0;
3343}
3344
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303345static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 const struct audio_config *config)
3347{
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303348 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003350 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3351 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352}
3353
3354static int adev_open_input_stream(struct audio_hw_device *dev,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303355 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356 audio_devices_t devices,
3357 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303358 struct audio_stream_in **stream_in,
3359 audio_input_flags_t flags __unused,
3360 const char *address __unused,
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003361 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003362{
3363 struct audio_device *adev = (struct audio_device *)dev;
3364 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003365 int ret = 0, buffer_size, frame_size;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303366 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003367 bool is_low_latency = false;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369 *stream_in = NULL;
3370 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3371 return -EINVAL;
3372
3373 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003374
3375 if (!in) {
3376 ALOGE("failed to allocate input stream");
3377 return -ENOMEM;
3378 }
3379
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303380 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003381 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3382 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003383
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003384 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3385
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386 in->stream.common.get_sample_rate = in_get_sample_rate;
3387 in->stream.common.set_sample_rate = in_set_sample_rate;
3388 in->stream.common.get_buffer_size = in_get_buffer_size;
3389 in->stream.common.get_channels = in_get_channels;
3390 in->stream.common.get_format = in_get_format;
3391 in->stream.common.set_format = in_set_format;
3392 in->stream.common.standby = in_standby;
3393 in->stream.common.dump = in_dump;
3394 in->stream.common.set_parameters = in_set_parameters;
3395 in->stream.common.get_parameters = in_get_parameters;
3396 in->stream.common.add_audio_effect = in_add_audio_effect;
3397 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3398 in->stream.set_gain = in_set_gain;
3399 in->stream.read = in_read;
3400 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3401
3402 in->device = devices;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003403 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003404 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405 in->standby = 1;
3406 in->channel_mask = config->channel_mask;
3407
3408 /* Update config params with the requested sample rate and channels */
3409 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003410 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3411 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3412 is_low_latency = true;
3413#if LOW_LATENCY_CAPTURE_USE_CASE
3414 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3415#endif
3416 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003419 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003420
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303421 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkala3c0036d2014-12-17 16:45:10 +05303422 if (adev->mode != AUDIO_MODE_IN_CALL) {
3423 ret = -EINVAL;
3424 goto err_open;
Pavan Chikkala3ec42ef2014-11-21 20:57:48 +05303425 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303426 if (config->sample_rate == 0)
3427 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3428 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3429 config->sample_rate != 8000) {
3430 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3431 ret = -EINVAL;
3432 goto err_open;
3433 }
3434 if (config->format == AUDIO_FORMAT_DEFAULT)
3435 config->format = AUDIO_FORMAT_PCM_16_BIT;
3436 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3437 config->format = AUDIO_FORMAT_PCM_16_BIT;
3438 ret = -EINVAL;
3439 goto err_open;
3440 }
3441 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3442 in->config = pcm_config_afe_proxy_record;
3443 in->config.channels = channel_count;
3444 in->config.rate = config->sample_rate;
3445 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003446 if(audio_extn_ssr_get_enabled()) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303447 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003448 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3449 ret = -EINVAL;
3450 goto err_open;
3451 }
3452 } else {
Mingming Yindaf9c542014-09-16 17:41:33 -07003453 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003454 }
Mingming Yine62d7842013-10-25 16:26:03 -07003455 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08003456 audio_extn_compr_cap_format_supported(config->format) &&
3457 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303458 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003459 } else {
3460 in->config.channels = channel_count;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303461 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003462 buffer_size = get_input_buffer_size(config->sample_rate,
3463 config->format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003464 channel_count,
3465 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003466 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003467 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3468 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3469 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3470 (in->config.rate == 8000 || in->config.rate == 16000) &&
3471 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3472 voice_extn_compress_voip_open_input_stream(in);
3473 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003474 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003475
3476 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003477 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003478 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003479
3480err_open:
3481 free(in);
3482 *stream_in = NULL;
3483 return ret;
3484}
3485
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303486static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487 struct audio_stream_in *stream)
3488{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003489 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003490 struct stream_in *in = (struct stream_in *)stream;
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303491 struct audio_device *adev = in->dev;
3492
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303493 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003494
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003495 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303496 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003497 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303498 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003499 if (ret != 0)
3500 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3501 __func__, ret);
3502 } else
3503 in_standby(&stream->common);
3504
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303505 if (audio_extn_ssr_get_enabled() &&
3506 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003507 audio_extn_ssr_deinit();
3508 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003509 free(stream);
3510
Mingming Yine62d7842013-10-25 16:26:03 -07003511 if(audio_extn_compr_cap_enabled() &&
3512 audio_extn_compr_cap_format_supported(in->config.format))
3513 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003514 return;
3515}
3516
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303517static int adev_dump(const audio_hw_device_t *device __unused,
3518 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003519{
3520 return 0;
3521}
3522
Steve Kondik3abbbc82014-11-29 14:14:43 -08003523/* verifies input and output devices and their capabilities.
3524 *
3525 * This verification is required when enabling extended bit-depth or
3526 * sampling rates, as not all qcom products support it.
3527 *
3528 * Suitable for calling only on initialization such as adev_open().
3529 * It fills the audio_device use_case_table[] array.
3530 *
3531 * Has a side-effect that it needs to configure audio routing / devices
3532 * in order to power up the devices and read the device parameters.
3533 * It does not acquire any hw device lock. Should restore the devices
3534 * back to "normal state" upon completion.
3535 */
3536static int adev_verify_devices(struct audio_device *adev)
3537{
3538 /* enumeration is a bit difficult because one really wants to pull
3539 * the use_case, device id, etc from the hidden pcm_device_table[].
3540 * In this case there are the following use cases and device ids.
3541 *
3542 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3543 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3544 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3545 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3546 * [USECASE_AUDIO_RECORD] = {0, 0},
3547 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3548 * [USECASE_VOICE_CALL] = {2, 2},
3549 *
3550 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3551 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3552 */
3553
3554 /* should be the usecases enabled in adev_open_input_stream() */
3555 static const int test_in_usecases[] = {
3556 USECASE_AUDIO_RECORD,
3557 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3558 };
3559 /* should be the usecases enabled in adev_open_output_stream()*/
3560 static const int test_out_usecases[] = {
3561 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3562 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3563 };
3564 static const usecase_type_t usecase_type_by_dir[] = {
3565 PCM_PLAYBACK,
3566 PCM_CAPTURE,
3567 };
3568 static const unsigned flags_by_dir[] = {
3569 PCM_OUT,
3570 PCM_IN,
3571 };
3572
3573 size_t i;
3574 unsigned dir;
3575 const unsigned card_id = adev->snd_card;
3576 char info[512]; /* for possible debug info */
3577
3578 for (dir = 0; dir < 2; ++dir) {
3579 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3580 const unsigned flags_dir = flags_by_dir[dir];
3581 const size_t testsize =
3582 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3583 const int *testcases =
3584 dir ? test_in_usecases : test_out_usecases;
3585 const audio_devices_t audio_device =
3586 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3587
3588 for (i = 0; i < testsize; ++i) {
3589 const audio_usecase_t audio_usecase = testcases[i];
3590 int device_id;
3591 snd_device_t snd_device;
3592 struct pcm_params **pparams;
3593 struct stream_out out;
3594 struct stream_in in;
3595 struct audio_usecase uc_info;
3596 int retval;
3597
3598 pparams = &adev->use_case_table[audio_usecase];
3599 pcm_params_free(*pparams); /* can accept null input */
3600 *pparams = NULL;
3601
3602 /* find the device ID for the use case (signed, for error) */
3603 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3604 if (device_id < 0)
3605 continue;
3606
3607 /* prepare structures for device probing */
3608 memset(&uc_info, 0, sizeof(uc_info));
3609 uc_info.id = audio_usecase;
3610 uc_info.type = usecase_type;
3611 if (dir) {
3612 adev->active_input = &in;
3613 memset(&in, 0, sizeof(in));
3614 in.device = audio_device;
3615 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3616 uc_info.stream.in = &in;
3617 } else {
3618 adev->active_input = NULL;
3619 }
3620 memset(&out, 0, sizeof(out));
3621 out.devices = audio_device; /* only field needed in select_devices */
3622 uc_info.stream.out = &out;
3623 uc_info.devices = audio_device;
3624 uc_info.in_snd_device = SND_DEVICE_NONE;
3625 uc_info.out_snd_device = SND_DEVICE_NONE;
3626 list_add_tail(&adev->usecase_list, &uc_info.list);
3627
3628 /* select device - similar to start_(in/out)put_stream() */
3629 retval = select_devices(adev, audio_usecase);
3630 if (retval >= 0) {
3631 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3632#if LOG_NDEBUG == 0
3633 if (*pparams) {
3634 ALOGV("%s: (%s) card %d device %d", __func__,
3635 dir ? "input" : "output", card_id, device_id);
3636 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
3637 ALOGV(info); /* print parameters */
3638 } else {
3639 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3640 }
3641#endif
3642 }
3643
3644 /* deselect device - similar to stop_(in/out)put_stream() */
3645 /* 1. Get and set stream specific mixer controls */
3646 retval = disable_audio_route(adev, &uc_info);
3647 /* 2. Disable the rx device */
3648 retval = disable_snd_device(adev,
3649 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
3650 list_remove(&uc_info.list);
3651 }
3652 }
3653 adev->active_input = NULL; /* restore adev state */
3654 return 0;
3655}
3656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657static int adev_close(hw_device_t *device)
3658{
Steve Kondik3abbbc82014-11-29 14:14:43 -08003659 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003660 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003661
3662 if (!adev)
3663 return 0;
3664
3665 pthread_mutex_lock(&adev_init_lock);
3666
3667 if ((--audio_device_ref_count) == 0) {
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303668 if (amplifier_close() != 0)
3669 ALOGE("Amplifier close failed");
Kiran Kandide144c82013-11-20 15:58:32 -08003670 audio_extn_listen_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07003671 audio_route_free(adev->audio_route);
3672 free(adev->snd_dev_ref_cnt);
3673 platform_deinit(adev->platform);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003674 audio_extn_extspk_deinit(adev->extspk);
Steve Kondik3abbbc82014-11-29 14:14:43 -08003675 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3676 pcm_params_free(adev->use_case_table[i]);
3677 }
Kiran Kandi910e1862013-10-29 13:29:42 -07003678 free(device);
3679 adev = NULL;
3680 }
3681 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682 return 0;
3683}
3684
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003685/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3686 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3687 * just that it _might_ work.
3688 */
3689static int period_size_is_plausible_for_low_latency(int period_size)
3690{
3691 switch (period_size) {
3692 case 160:
3693 case 240:
3694 case 320:
3695 case 480:
3696 return 1;
3697 default:
3698 return 0;
3699 }
3700}
3701
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003702static int adev_open(const hw_module_t *module, const char *name,
3703 hw_device_t **device)
3704{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003705 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003706
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003707 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3709
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003710 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003711 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003712 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003713 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003714 ALOGD("%s: returning existing instance of adev", __func__);
3715 ALOGD("%s: exit", __func__);
3716 pthread_mutex_unlock(&adev_init_lock);
3717 return 0;
3718 }
3719
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003720 adev = calloc(1, sizeof(struct audio_device));
3721
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003722 if (!adev) {
3723 pthread_mutex_unlock(&adev_init_lock);
3724 return -ENOMEM;
3725 }
3726
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003727 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3728
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003729 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3730 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3731 adev->device.common.module = (struct hw_module_t *)module;
3732 adev->device.common.close = adev_close;
3733
3734 adev->device.init_check = adev_init_check;
3735 adev->device.set_voice_volume = adev_set_voice_volume;
3736 adev->device.set_master_volume = adev_set_master_volume;
3737 adev->device.get_master_volume = adev_get_master_volume;
3738 adev->device.set_master_mute = adev_set_master_mute;
3739 adev->device.get_master_mute = adev_get_master_mute;
3740 adev->device.set_mode = adev_set_mode;
3741 adev->device.set_mic_mute = adev_set_mic_mute;
3742 adev->device.get_mic_mute = adev_get_mic_mute;
3743 adev->device.set_parameters = adev_set_parameters;
3744 adev->device.get_parameters = adev_get_parameters;
3745 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3746 adev->device.open_output_stream = adev_open_output_stream;
3747 adev->device.close_output_stream = adev_close_output_stream;
3748 adev->device.open_input_stream = adev_open_input_stream;
3749 adev->device.close_input_stream = adev_close_input_stream;
3750 adev->device.dump = adev_dump;
3751
3752 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003753 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003754 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003755 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003758 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003759 /* adev->cur_hdmi_channels = 0; by calloc() */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08003760 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3761 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003762 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003763 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003764 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly9b7e96b2014-02-14 14:45:49 -08003765 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003766 adev->offload_usecases_state = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303768 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3769 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
3770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003771 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003772 adev->platform = platform_init(adev);
3773 if (!adev->platform) {
3774 free(adev->snd_dev_ref_cnt);
3775 free(adev);
3776 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3777 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003778 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003779 return -EINVAL;
3780 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003781
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303782 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
Eric Laurentda46bfb2014-08-25 22:39:29 -05003783 adev->extspk = audio_extn_extspk_init(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303784
Eric Laurentc4aef752013-09-12 17:45:53 -07003785 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3786 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3787 if (adev->visualizer_lib == NULL) {
3788 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3789 } else {
3790 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3791 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003792 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003793 "visualizer_hal_start_output");
3794 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003795 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003796 "visualizer_hal_stop_output");
3797 }
3798 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003799 audio_extn_listen_init(adev, adev->snd_card);
Eric Laurentc4aef752013-09-12 17:45:53 -07003800
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003801 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3802 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3803 if (adev->offload_effects_lib == NULL) {
3804 ALOGE("%s: DLOPEN failed for %s", __func__,
3805 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3806 } else {
3807 ALOGV("%s: DLOPEN successful for %s", __func__,
3808 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3809 adev->offload_effects_start_output =
3810 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3811 "offload_effects_bundle_hal_start_output");
3812 adev->offload_effects_stop_output =
3813 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3814 "offload_effects_bundle_hal_stop_output");
3815 }
3816 }
3817
Dan Pasanend4c2ca92015-08-10 19:47:43 -05003818 if (amplifier_open() != 0)
3819 ALOGE("Amplifier initialization failed");
3820
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821 *device = &adev->device.common;
Steve Kondik3abbbc82014-11-29 14:14:43 -08003822 if (k_enable_extended_precision)
3823 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003824
Kiran Kandi910e1862013-10-29 13:29:42 -07003825 audio_device_ref_count++;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003826
3827 char value[PROPERTY_VALUE_MAX];
3828 int trial;
3829 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3830 trial = atoi(value);
3831 if (period_size_is_plausible_for_low_latency(trial)) {
3832 pcm_config_low_latency.period_size = trial;
3833 pcm_config_low_latency.start_threshold = trial / 4;
3834 pcm_config_low_latency.avail_min = trial / 4;
3835 configured_low_latency_capture_period_size = trial;
3836 }
3837 }
3838 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3839 trial = atoi(value);
3840 if (period_size_is_plausible_for_low_latency(trial)) {
3841 configured_low_latency_capture_period_size = trial;
3842 }
3843 }
3844
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003845 pthread_mutex_unlock(&adev_init_lock);
3846
Eric Laurent994a6932013-07-17 11:51:42 -07003847 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 return 0;
3849}
3850
3851static struct hw_module_methods_t hal_module_methods = {
3852 .open = adev_open,
3853};
3854
3855struct audio_module HAL_MODULE_INFO_SYM = {
3856 .common = {
3857 .tag = HARDWARE_MODULE_TAG,
3858 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3859 .hal_api_version = HARDWARE_HAL_API_VERSION,
3860 .id = AUDIO_HARDWARE_MODULE_ID,
3861 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003862 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003863 .methods = &hal_module_methods,
3864 },
3865};