blob: b3b1fc7ddfcd8c2babab11ff850444629eb5f1a6 [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 Kondik6288f9e2014-12-27 13:36:30 -0800593 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 Kondik6288f9e2014-12-27 13:36:30 -0800598 audio_extn_listen_update_status(snd_device,
599 LISTEN_EVENT_SND_DEVICE_BUSY);
Kiran Kandide144c82013-11-20 15:58:32 -0800600
Ethan Chen6720ae62015-07-03 21:35:30 -0700601 amplifier_enable_devices(snd_device, true);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700602 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800603 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800604 return 0;
605}
606
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700607int disable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700608 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800609{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700610 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
611
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800612 if (snd_device < SND_DEVICE_MIN ||
613 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800614 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800615 return -EINVAL;
616 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700617 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
618 ALOGE("%s: device ref cnt is already 0", __func__);
619 return -EINVAL;
620 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700621
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700622 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700623
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700624 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
625 ALOGE("%s: Invalid sound device returned", __func__);
626 return -EINVAL;
627 }
628
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700629 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700630 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700631 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800632 /* exit usb play back thread */
633 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
634 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
635 audio_extn_usb_stop_playback();
636
637 /* exit usb capture thread */
638 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Rajshekar Eashwarappa4dfa0752014-10-02 20:18:20 +0530639 audio_extn_usb_stop_capture();
Tony Layher692f19a2015-01-03 13:16:45 -0500640
641 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
642 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700643 audio_extn_spkr_prot_is_enabled()) {
644 audio_extn_spkr_prot_stop_processing();
Ethan Chen6720ae62015-07-03 21:35:30 -0700645 } else {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700646 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ethan Chen6720ae62015-07-03 21:35:30 -0700647 amplifier_enable_devices(snd_device, false);
648 }
Kiran Kandide144c82013-11-20 15:58:32 -0800649
Steve Kondik6288f9e2014-12-27 13:36:30 -0800650 audio_extn_listen_update_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800651 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700652 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700653
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800654 return 0;
655}
656
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700657static void check_usecases_codec_backend(struct audio_device *adev,
658 struct audio_usecase *uc_info,
659 snd_device_t snd_device)
660{
661 struct listnode *node;
662 struct audio_usecase *usecase;
663 bool switch_device[AUDIO_USECASE_MAX];
664 int i, num_uc_to_switch = 0;
665
666 /*
667 * This function is to make sure that all the usecases that are active on
668 * the hardware codec backend are always routed to any one device that is
669 * handled by the hardware codec.
670 * For example, if low-latency and deep-buffer usecases are currently active
671 * on speaker and out_set_parameters(headset) is received on low-latency
672 * output, then we have to make sure deep-buffer is also switched to headset,
673 * because of the limitation that both the devices cannot be enabled
674 * at the same time as they share the same backend.
675 */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800676 /*
677 * This call is to check if we need to force routing for a particular stream
678 * If there is a backend configuration change for the device when a
679 * new stream starts, then ADM needs to be closed and re-opened with the new
680 * configuraion. This call check if we need to re-route all the streams
681 * associated with the backend. Touch tone + 24 bit playback.
682 */
683 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
684
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700685 /* Disable all the usecases on the shared backend other than the
686 specified usecase */
687 for (i = 0; i < AUDIO_USECASE_MAX; i++)
688 switch_device[i] = false;
689
690 list_for_each(node, &adev->usecase_list) {
691 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800692 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700693 usecase != uc_info &&
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800694 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700695 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
696 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
697 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700698 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700699 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700700 switch_device[usecase->id] = true;
701 num_uc_to_switch++;
702 }
703 }
704
705 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700706 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700707
708 list_for_each(node, &adev->usecase_list) {
709 usecase = node_to_item(node, struct audio_usecase, list);
710 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700711 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700712 }
713 }
714
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700715 list_for_each(node, &adev->usecase_list) {
716 usecase = node_to_item(node, struct audio_usecase, list);
717 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700718 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700719 }
720 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700722 /* Re-route all the usecases on the shared backend other than the
723 specified usecase to new snd devices */
724 list_for_each(node, &adev->usecase_list) {
725 usecase = node_to_item(node, struct audio_usecase, list);
726 /* Update the out_snd_device only before enabling the audio route */
727 if (switch_device[usecase->id] ) {
728 usecase->out_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530729 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
730 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700731 }
732 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700733 }
734}
735
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700736static void check_and_route_capture_usecases(struct audio_device *adev,
737 struct audio_usecase *uc_info,
738 snd_device_t snd_device)
739{
740 struct listnode *node;
741 struct audio_usecase *usecase;
742 bool switch_device[AUDIO_USECASE_MAX];
743 int i, num_uc_to_switch = 0;
744
745 /*
746 * This function is to make sure that all the active capture usecases
747 * are always routed to the same input sound device.
748 * For example, if audio-record and voice-call usecases are currently
749 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
750 * is received for voice call then we have to make sure that audio-record
751 * usecase is also switched to earpiece i.e. voice-dmic-ef,
752 * because of the limitation that two devices cannot be enabled
753 * at the same time if they share the same backend.
754 */
755 for (i = 0; i < AUDIO_USECASE_MAX; i++)
756 switch_device[i] = false;
757
758 list_for_each(node, &adev->usecase_list) {
759 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800760 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700761 usecase != uc_info &&
Avinash Vaish44014792015-03-27 14:46:04 +0530762 usecase->in_snd_device != snd_device &&
763 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700764 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
765 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700766 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700767 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700768 switch_device[usecase->id] = true;
769 num_uc_to_switch++;
770 }
771 }
772
773 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700774 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700775
776 list_for_each(node, &adev->usecase_list) {
777 usecase = node_to_item(node, struct audio_usecase, list);
778 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700779 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800780 }
781 }
782
783 list_for_each(node, &adev->usecase_list) {
784 usecase = node_to_item(node, struct audio_usecase, list);
785 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700786 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700787 }
788 }
789
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700790 /* Re-route all the usecases on the shared backend other than the
791 specified usecase to new snd devices */
792 list_for_each(node, &adev->usecase_list) {
793 usecase = node_to_item(node, struct audio_usecase, list);
794 /* Update the in_snd_device only before enabling the audio route */
795 if (switch_device[usecase->id] ) {
796 usecase->in_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530797 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
798 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700799 }
800 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700801 }
802}
803
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800804/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700805static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800806{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700807 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700808 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800809
810 switch (channels) {
811 /*
812 * Do not handle stereo output in Multi-channel cases
813 * Stereo case is handled in normal playback path
814 */
815 case 6:
816 ALOGV("%s: HDMI supports 5.1", __func__);
817 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
818 break;
819 case 8:
820 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
821 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
822 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
823 break;
824 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700825 ALOGE("HDMI does not support multi channel playback");
826 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800827 break;
828 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700829 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800830}
831
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700832static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
833{
834 struct audio_usecase *usecase;
835 struct listnode *node;
836
837 list_for_each(node, &adev->usecase_list) {
838 usecase = node_to_item(node, struct audio_usecase, list);
839 if (usecase->type == VOICE_CALL) {
840 ALOGV("%s: usecase id %d", __func__, usecase->id);
841 return usecase->id;
842 }
843 }
844 return USECASE_INVALID;
845}
846
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700847struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700848 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700849{
850 struct audio_usecase *usecase;
851 struct listnode *node;
852
853 list_for_each(node, &adev->usecase_list) {
854 usecase = node_to_item(node, struct audio_usecase, list);
855 if (usecase->id == uc_id)
856 return usecase;
857 }
858 return NULL;
859}
860
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700861int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800862{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800863 snd_device_t out_snd_device = SND_DEVICE_NONE;
864 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700865 struct audio_usecase *usecase = NULL;
866 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800867 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800868 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800869 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800870 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800872
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 usecase = get_usecase_from_list(adev, uc_id);
874 if (usecase == NULL) {
875 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
876 return -EINVAL;
877 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800878
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800879 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800880 (usecase->type == VOIP_CALL) ||
881 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700882 out_snd_device = platform_get_output_snd_device(adev->platform,
883 usecase->stream.out->devices);
884 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700885 usecase->devices = usecase->stream.out->devices;
886 } else {
887 /*
888 * If the voice call is active, use the sound devices of voice call usecase
889 * so that it would not result any device switch. All the usecases will
890 * be switched to new device when select_devices() is called for voice call
891 * usecase. This is to avoid switching devices for voice call when
892 * check_usecases_codec_backend() is called below.
893 */
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -0700894 if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700895 vc_usecase = get_usecase_from_list(adev,
896 get_voice_usecase_id_from_list(adev));
Mingming Yin6c23f382014-08-14 00:00:51 -0700897 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
898 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700899 in_snd_device = vc_usecase->in_snd_device;
900 out_snd_device = vc_usecase->out_snd_device;
901 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800902 } else if (voice_extn_compress_voip_is_active(adev)) {
903 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin6c23f382014-08-14 00:00:51 -0700904 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish6a4c3372014-06-25 12:20:37 +0530905 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin6c23f382014-08-14 00:00:51 -0700906 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800907 in_snd_device = voip_usecase->in_snd_device;
908 out_snd_device = voip_usecase->out_snd_device;
909 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800910 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800911 hfp_ucid = audio_extn_hfp_get_usecase();
912 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin6c23f382014-08-14 00:00:51 -0700913 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800914 in_snd_device = hfp_usecase->in_snd_device;
915 out_snd_device = hfp_usecase->out_snd_device;
916 }
Vimal Puthanveed8fa9eab2014-01-07 16:47:47 -0800917 } else if (audio_extn_hfp_is_active(adev)) {
918 hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
919 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
920 in_snd_device = hfp_usecase->in_snd_device;
921 out_snd_device = hfp_usecase->out_snd_device;
922 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700923 }
924 if (usecase->type == PCM_PLAYBACK) {
925 usecase->devices = usecase->stream.out->devices;
926 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700927 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700928 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700929 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700930 if (usecase->stream.out == adev->primary_output &&
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530931 adev->active_input ) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700932 select_devices(adev, adev->active_input->usecase);
933 }
934 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700935 } else if (usecase->type == PCM_CAPTURE) {
936 usecase->devices = usecase->stream.in->device;
937 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700938 if (in_snd_device == SND_DEVICE_NONE) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530939 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530940 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 -0700941 adev->primary_output && !adev->primary_output->standby) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530942 out_device = adev->primary_output->devices;
943 } else if(usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
944 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700945 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530946 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700947 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700948 }
949 }
950
951 if (out_snd_device == usecase->out_snd_device &&
952 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800953 return 0;
954 }
955
sangwoobc677242013-08-08 16:53:43 +0900956 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700957 out_snd_device, platform_get_snd_device_name(out_snd_device),
958 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800959
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800960 /*
961 * Limitation: While in call, to do a device switch we need to disable
962 * and enable both RX and TX devices though one of them is same as current
963 * device.
964 */
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800965 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700966 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800967 }
968
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700969 /* Disable current sound devices */
970 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700971 disable_audio_route(adev, usecase);
972 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973 }
974
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700975 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700976 disable_audio_route(adev, usecase);
977 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800978 }
979
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700980 /* Enable new sound devices */
981 if (out_snd_device != SND_DEVICE_NONE) {
982 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
983 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700984 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800985 }
986
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700987 if (in_snd_device != SND_DEVICE_NONE) {
988 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700989 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700990 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700991
Avinash Vaish8005dc82014-07-24 15:36:33 +0530992 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700993 status = platform_switch_voice_call_device_post(adev->platform,
994 out_snd_device,
995 in_snd_device);
Avinash Vaish8005dc82014-07-24 15:36:33 +0530996 enable_audio_route_for_voice_usecases(adev, usecase);
997 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800998
sangwoo170731f2013-06-08 15:36:36 +0900999 usecase->in_snd_device = in_snd_device;
1000 usecase->out_snd_device = out_snd_device;
1001
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001002 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001003
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301004 /* Rely on amplifier_set_devices to distinguish between in/out devices */
Ethan Chen79c356c2015-06-07 12:26:14 -07001005 amplifier_set_input_devices(in_snd_device);
1006 amplifier_set_output_devices(out_snd_device);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301007
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001008 /* Applicable only on the targets that has external modem.
1009 * Enable device command should be sent to modem only after
1010 * enabling voice call mixer controls
1011 */
1012 if (usecase->type == VOICE_CALL)
1013 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1014 out_snd_device,
1015 in_snd_device);
1016
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301017 ALOGD("%s: done",__func__);
1018
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001019 return status;
1020}
1021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001022static int stop_input_stream(struct stream_in *in)
1023{
1024 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025 struct audio_usecase *uc_info;
1026 struct audio_device *adev = in->dev;
1027
Eric Laurentc8400632013-02-14 19:04:54 -08001028 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029
Eric Laurent994a6932013-07-17 11:51:42 -07001030 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001031 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032 uc_info = get_usecase_from_list(adev, in->usecase);
1033 if (uc_info == NULL) {
1034 ALOGE("%s: Could not find the usecase (%d) in the list",
1035 __func__, in->usecase);
1036 return -EINVAL;
1037 }
1038
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001039 /* Close in-call recording streams */
1040 voice_check_and_stop_incall_rec_usecase(adev, in);
1041
Eric Laurent150dbfe2013-02-27 14:31:02 -08001042 /* 1. Disable stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001043 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001044
1045 /* 2. Disable the tx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001046 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001048 list_remove(&uc_info->list);
1049 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050
Eric Laurent994a6932013-07-17 11:51:42 -07001051 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001052 return ret;
1053}
1054
1055int start_input_stream(struct stream_in *in)
1056{
1057 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001058 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001059 struct audio_usecase *uc_info;
1060 struct audio_device *adev = in->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301061 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062
Ramjee Singh240ac652015-07-31 16:12:29 +05301063 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1064 if (get_usecase_from_list(adev, usecase) == NULL)
1065 in->usecase = usecase;
1066
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301067 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1068 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001069
Naresh Tannirucef332d2014-06-04 18:17:56 +05301070 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
1071 ALOGE("%s: sound card is not active/SSR returning error ", __func__);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301072 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301073 goto error_config;
1074 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301075
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001076 /* Check if source matches incall recording usecase criteria */
1077 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1078 if (ret)
1079 goto error_config;
1080 else
1081 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1082
Ramjee Singh240ac652015-07-31 16:12:29 +05301083 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1084 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1085 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1086 goto error_config;
1087 }
1088
Eric Laurentb23d5282013-05-14 15:27:20 -07001089 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001090 if (in->pcm_device_id < 0) {
1091 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1092 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001093 ret = -EINVAL;
1094 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001095 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096
1097 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001099
1100 if (!uc_info) {
1101 ret = -ENOMEM;
1102 goto error_config;
1103 }
1104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105 uc_info->id = in->usecase;
1106 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001107 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001108 uc_info->devices = in->device;
1109 uc_info->in_snd_device = SND_DEVICE_NONE;
1110 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001112 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001113 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001114
Eric Laurentc8400632013-02-14 19:04:54 -08001115 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301116 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1117
1118 unsigned int flags = PCM_IN;
1119 unsigned int pcm_open_retry_entry_count = 0;
1120
1121 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1122 flags |= PCM_MMAP | PCM_NOIRQ;
1123 pcm_open_retry_entry_count = PROXY_OPEN_RETRY_COUNT;
1124 }
1125
1126 while(1) {
1127 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1128 flags, &in->config);
1129 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1130 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1131 if (in->pcm != NULL) {
1132 pcm_close(in->pcm);
1133 in->pcm = NULL;
1134 }
1135 if (pcm_open_retry_entry_count-- == 0) {
1136 ret = -EIO;
1137 goto error_open;
1138 }
1139 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1140 continue;
1141 }
1142 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001143 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301144
Eric Laurent994a6932013-07-17 11:51:42 -07001145 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001146 return ret;
1147
1148error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001149 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001150
1151error_config:
1152 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001153 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001154
1155 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156}
1157
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001158/* must be called with out->lock locked */
1159static int send_offload_cmd_l(struct stream_out* out, int command)
1160{
1161 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1162
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001163 if (!cmd) {
1164 ALOGE("failed to allocate mem for command 0x%x", command);
1165 return -ENOMEM;
1166 }
1167
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001168 ALOGVV("%s %d", __func__, command);
1169
1170 cmd->cmd = command;
1171 list_add_tail(&out->offload_cmd_list, &cmd->node);
1172 pthread_cond_signal(&out->offload_cond);
1173 return 0;
1174}
1175
1176/* must be called iwth out->lock locked */
1177static void stop_compressed_output_l(struct stream_out *out)
1178{
1179 out->offload_state = OFFLOAD_STATE_IDLE;
1180 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001181 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001182 if (out->compr != NULL) {
1183 compress_stop(out->compr);
1184 while (out->offload_thread_blocked) {
1185 pthread_cond_wait(&out->cond, &out->lock);
1186 }
1187 }
1188}
1189
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001190bool is_offload_usecase(audio_usecase_t uc_id)
1191{
1192 unsigned int i;
1193 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1194 if (uc_id == offload_usecases[i])
1195 return true;
1196 }
1197 return false;
1198}
1199
1200static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1201{
1202 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1203 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1204 char value[PROPERTY_VALUE_MAX] = {0};
1205
1206 property_get("audio.offload.multiple.enabled", value, NULL);
1207 if (!(atoi(value) || !strncmp("true", value, 4)))
1208 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1209
1210 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1211 for (i = 0; i < num_usecase; i++) {
1212 if (!(adev->offload_usecases_state & (0x1<<i))) {
1213 adev->offload_usecases_state |= 0x1 << i;
1214 ret = offload_usecases[i];
1215 break;
1216 }
1217 }
1218 ALOGV("%s: offload usecase is %d", __func__, ret);
1219 return ret;
1220}
1221
1222static void free_offload_usecase(struct audio_device *adev,
1223 audio_usecase_t uc_id)
1224{
1225 unsigned int i;
1226 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1227 if (offload_usecases[i] == uc_id) {
1228 adev->offload_usecases_state &= ~(0x1<<i);
1229 break;
1230 }
1231 }
1232 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1233}
1234
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001235static void *offload_thread_loop(void *context)
1236{
1237 struct stream_out *out = (struct stream_out *) context;
1238 struct listnode *item;
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001239 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001240
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001241 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1242 set_sched_policy(0, SP_FOREGROUND);
1243 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1244
1245 ALOGV("%s", __func__);
1246 pthread_mutex_lock(&out->lock);
1247 for (;;) {
1248 struct offload_cmd *cmd = NULL;
1249 stream_callback_event_t event;
1250 bool send_callback = false;
1251
1252 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1253 __func__, list_empty(&out->offload_cmd_list),
1254 out->offload_state);
1255 if (list_empty(&out->offload_cmd_list)) {
1256 ALOGV("%s SLEEPING", __func__);
1257 pthread_cond_wait(&out->offload_cond, &out->lock);
1258 ALOGV("%s RUNNING", __func__);
1259 continue;
1260 }
1261
1262 item = list_head(&out->offload_cmd_list);
1263 cmd = node_to_item(item, struct offload_cmd, node);
1264 list_remove(item);
1265
1266 ALOGVV("%s STATE %d CMD %d out->compr %p",
1267 __func__, out->offload_state, cmd->cmd, out->compr);
1268
1269 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1270 free(cmd);
1271 break;
1272 }
1273
1274 if (out->compr == NULL) {
1275 ALOGE("%s: Compress handle is NULL", __func__);
1276 pthread_cond_signal(&out->cond);
1277 continue;
1278 }
1279 out->offload_thread_blocked = true;
1280 pthread_mutex_unlock(&out->lock);
1281 send_callback = false;
1282 switch(cmd->cmd) {
1283 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Steve Kondik05c17962015-02-25 00:55:50 -08001284 ALOGV("copl(%x):calling compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001285 compress_wait(out->compr, -1);
Steve Kondik05c17962015-02-25 00:55:50 -08001286 ALOGV("copl(%x):out of compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001287 send_callback = true;
1288 event = STREAM_CBK_EVENT_WRITE_READY;
1289 break;
1290 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001291 ret = compress_next_track(out->compr);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301292 if(ret == 0) {
Steve Kondik05c17962015-02-25 00:55:50 -08001293 ALOGV("copl(%p):calling compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301294 ret = compress_partial_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001295 ALOGV("copl(%p):out of compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301296 if (ret < 0)
1297 ret = -errno;
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301298 }
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301299 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001300 compress_drain(out->compr);
1301 else
1302 ALOGE("%s: Next track returned error %d",__func__, ret);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301303
1304 if (ret != -ENETRESET) {
1305 send_callback = true;
1306 event = STREAM_CBK_EVENT_DRAIN_READY;
1307
1308 /* Resend the metadata for next iteration */
1309 out->send_new_metadata = 1;
1310 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1311 } else
1312 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001313 break;
1314 case OFFLOAD_CMD_DRAIN:
Steve Kondik05c17962015-02-25 00:55:50 -08001315 ALOGV("copl(%x):calling compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001316 compress_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001317 ALOGV("copl(%x):out of compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001318 send_callback = true;
1319 event = STREAM_CBK_EVENT_DRAIN_READY;
1320 break;
1321 default:
1322 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1323 break;
1324 }
1325 pthread_mutex_lock(&out->lock);
1326 out->offload_thread_blocked = false;
1327 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001328 if (send_callback) {
Ravi Kumar Alamanda3d316172014-12-02 19:21:51 -08001329 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001330 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001331 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001332 free(cmd);
1333 }
1334
1335 pthread_cond_signal(&out->cond);
1336 while (!list_empty(&out->offload_cmd_list)) {
1337 item = list_head(&out->offload_cmd_list);
1338 list_remove(item);
1339 free(node_to_item(item, struct offload_cmd, node));
1340 }
1341 pthread_mutex_unlock(&out->lock);
1342
1343 return NULL;
1344}
1345
1346static int create_offload_callback_thread(struct stream_out *out)
1347{
1348 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1349 list_init(&out->offload_cmd_list);
1350 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1351 offload_thread_loop, out);
1352 return 0;
1353}
1354
1355static int destroy_offload_callback_thread(struct stream_out *out)
1356{
1357 pthread_mutex_lock(&out->lock);
1358 stop_compressed_output_l(out);
1359 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1360
1361 pthread_mutex_unlock(&out->lock);
1362 pthread_join(out->offload_thread, (void **) NULL);
1363 pthread_cond_destroy(&out->offload_cond);
1364
1365 return 0;
1366}
1367
Eric Laurent07eeafd2013-10-06 12:52:49 -07001368static bool allow_hdmi_channel_config(struct audio_device *adev)
1369{
1370 struct listnode *node;
1371 struct audio_usecase *usecase;
1372 bool ret = true;
1373
1374 list_for_each(node, &adev->usecase_list) {
1375 usecase = node_to_item(node, struct audio_usecase, list);
1376 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1377 /*
1378 * If voice call is already existing, do not proceed further to avoid
1379 * disabling/enabling both RX and TX devices, CSD calls, etc.
1380 * Once the voice call done, the HDMI channels can be configured to
1381 * max channels of remaining use cases.
1382 */
1383 if (usecase->id == USECASE_VOICE_CALL) {
1384 ALOGD("%s: voice call is active, no change in HDMI channels",
1385 __func__);
1386 ret = false;
1387 break;
1388 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1389 ALOGD("%s: multi channel playback is active, "
1390 "no change in HDMI channels", __func__);
1391 ret = false;
1392 break;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001393 } else if (is_offload_usecase(usecase->id) &&
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301394 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin3ed162b2014-02-24 17:56:01 -08001395 ALOGD("%s: multi-channel(%x) compress offload playback is active, "
1396 "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
1397 ret = false;
1398 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001399 }
1400 }
1401 }
1402 return ret;
1403}
1404
1405static int check_and_set_hdmi_channels(struct audio_device *adev,
1406 unsigned int channels)
1407{
1408 struct listnode *node;
1409 struct audio_usecase *usecase;
1410
1411 /* Check if change in HDMI channel config is allowed */
1412 if (!allow_hdmi_channel_config(adev))
1413 return 0;
1414
1415 if (channels == adev->cur_hdmi_channels) {
Mingming Yin10fef6a2013-11-26 17:17:01 -08001416 ALOGD("%s: Requested channels are same as current channels(%d)", __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001417 return 0;
1418 }
1419
1420 platform_set_hdmi_channels(adev->platform, channels);
1421 adev->cur_hdmi_channels = channels;
1422
1423 /*
1424 * Deroute all the playback streams routed to HDMI so that
1425 * the back end is deactivated. Note that backend will not
1426 * be deactivated if any one stream is connected to it.
1427 */
1428 list_for_each(node, &adev->usecase_list) {
1429 usecase = node_to_item(node, struct audio_usecase, list);
1430 if (usecase->type == PCM_PLAYBACK &&
1431 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001432 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001433 }
1434 }
1435
1436 /*
1437 * Enable all the streams disabled above. Now the HDMI backend
1438 * will be activated with new channel configuration
1439 */
1440 list_for_each(node, &adev->usecase_list) {
1441 usecase = node_to_item(node, struct audio_usecase, list);
1442 if (usecase->type == PCM_PLAYBACK &&
1443 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001444 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001445 }
1446 }
1447
1448 return 0;
1449}
1450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001451static int stop_output_stream(struct stream_out *out)
1452{
1453 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001454 struct audio_usecase *uc_info;
1455 struct audio_device *adev = out->dev;
1456
Eric Laurent994a6932013-07-17 11:51:42 -07001457 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001458 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001459 uc_info = get_usecase_from_list(adev, out->usecase);
1460 if (uc_info == NULL) {
1461 ALOGE("%s: Could not find the usecase (%d) in the list",
1462 __func__, out->usecase);
1463 return -EINVAL;
1464 }
1465
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001466 if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001467 if (adev->visualizer_stop_output != NULL)
1468 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1469 if (adev->offload_effects_stop_output != NULL)
1470 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1471 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001472
Eric Laurent150dbfe2013-02-27 14:31:02 -08001473 /* 1. Get and set stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001474 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475
1476 /* 2. Disable the rx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001477 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001478
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001479 list_remove(&uc_info->list);
1480 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001481
Eric Laurentda46bfb2014-08-25 22:39:29 -05001482 audio_extn_extspk_update(adev->extspk);
1483
Eric Laurent07eeafd2013-10-06 12:52:49 -07001484 /* Must be called after removing the usecase from list */
1485 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1486 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1487
Eric Laurent994a6932013-07-17 11:51:42 -07001488 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001489 return ret;
1490}
1491
1492int start_output_stream(struct stream_out *out)
1493{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494 int ret = 0;
Mingming Yin6c344432014-05-01 15:37:31 -07001495 int sink_channels = 0;
1496 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001497 struct audio_usecase *uc_info;
1498 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301499 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001501 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1502 ret = -EINVAL;
1503 goto error_config;
1504 }
1505
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301506 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1507 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1508 out->devices);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301509
Naresh Tannirucef332d2014-06-04 18:17:56 +05301510 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301511 ALOGE("%s: sound card is not active/SSR returning error", __func__);
1512 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301513 goto error_config;
1514 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301515
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301516 ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
1517 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001518 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001519 if (out->pcm_device_id < 0) {
1520 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1521 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001522 ret = -EINVAL;
1523 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001524 }
1525
1526 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001527
1528 if (!uc_info) {
1529 ret = -ENOMEM;
1530 goto error_config;
1531 }
1532
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001533 uc_info->id = out->usecase;
1534 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001535 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001536 uc_info->devices = out->devices;
1537 uc_info->in_snd_device = SND_DEVICE_NONE;
1538 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539
Eric Laurent07eeafd2013-10-06 12:52:49 -07001540 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001541 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Mingming Yin6c344432014-05-01 15:37:31 -07001542 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1543 if (!strncmp("true", prop_value, 4)) {
1544 sink_channels = platform_edid_get_max_channels(out->dev->platform);
1545 ALOGD("%s: set HDMI channel count[%d] based on sink capability", __func__, sink_channels);
1546 check_and_set_hdmi_channels(adev, sink_channels);
1547 } else {
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001548 if (is_offload_usecase(out->usecase))
Mingming Yin6c344432014-05-01 15:37:31 -07001549 check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in);
1550 else
1551 check_and_set_hdmi_channels(adev, out->config.channels);
1552 }
Mingming Yin10fef6a2013-11-26 17:17:01 -08001553 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001554
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001555 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001556
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557 select_devices(adev, out->usecase);
1558
Eric Laurentda46bfb2014-08-25 22:39:29 -05001559 audio_extn_extspk_update(adev->extspk);
1560
Steve Kondik3abbbc82014-11-29 14:14:43 -08001561 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1562 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
1563
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001564 if (!is_offload_usecase(out->usecase)) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301565 unsigned int flags = PCM_OUT;
1566 unsigned int pcm_open_retry_count = 0;
1567 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1568 flags |= PCM_MMAP | PCM_NOIRQ;
1569 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1570 } else
1571 flags |= PCM_MONOTONIC;
1572
1573 while (1) {
1574 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1575 flags, &out->config);
1576 if (out->pcm && !pcm_is_ready(out->pcm)) {
1577 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1578 if (out->pcm != NULL) {
1579 pcm_close(out->pcm);
1580 out->pcm = NULL;
1581 }
1582 if (pcm_open_retry_count-- == 0) {
1583 ret = -EIO;
1584 goto error_open;
1585 }
1586 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1587 continue;
1588 }
1589 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001590 }
1591 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001592 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001593 out->compr = compress_open(adev->snd_card,
1594 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001595 COMPRESS_IN, &out->compr_config);
1596 if (out->compr && !is_compress_ready(out->compr)) {
1597 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1598 compress_close(out->compr);
1599 out->compr = NULL;
1600 ret = -EIO;
1601 goto error_open;
1602 }
1603 if (out->offload_callback)
1604 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001605
Fred Oh1483d8a2015-03-04 18:42:34 -08001606 /* Since small bufs uses blocking writes, a write will be blocked
1607 for the default max poll time (20s) in the event of an SSR.
1608 Reduce the poll time to observe and deal with SSR faster.
1609 */
1610 if (out->use_small_bufs) {
1611 compress_set_max_poll_wait(out->compr, 1000);
1612 }
1613
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08001614#ifdef DS1_DOLBY_DDP_ENABLED
1615 if (audio_extn_is_dolby_format(out->format))
1616 audio_extn_dolby_send_ddp_endp_params(adev);
1617#endif
1618
Eric Laurentc4aef752013-09-12 17:45:53 -07001619 if (adev->visualizer_start_output != NULL)
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001620 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1621 if (adev->offload_effects_start_output != NULL)
1622 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001623 }
Eric Laurent994a6932013-07-17 11:51:42 -07001624 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001626error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001627 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001628error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001629 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001630}
1631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001632static int check_input_parameters(uint32_t sample_rate,
1633 audio_format_t format,
1634 int channel_count)
1635{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001636 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001637
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001638 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001639 !voice_extn_compress_voip_is_format_supported(format) &&
1640 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001641
1642 switch (channel_count) {
1643 case 1:
1644 case 2:
1645 case 6:
1646 break;
1647 default:
1648 ret = -EINVAL;
1649 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001650
1651 switch (sample_rate) {
1652 case 8000:
1653 case 11025:
1654 case 12000:
1655 case 16000:
1656 case 22050:
1657 case 24000:
1658 case 32000:
1659 case 44100:
1660 case 48000:
1661 break;
1662 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001663 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664 }
1665
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001666 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667}
1668
1669static size_t get_input_buffer_size(uint32_t sample_rate,
1670 audio_format_t format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001671 int channel_count,
1672 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673{
1674 size_t size = 0;
1675
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001676 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1677 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001678
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001679 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001680 if (is_low_latency)
1681 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001682 /* ToDo: should use frame_size computed based on the format and
1683 channel_count here. */
1684 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001686 /* make sure the size is multiple of 32 bytes
1687 * At 48 kHz mono 16-bit PCM:
1688 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1689 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1690 */
1691 size += 0x1f;
1692 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001693
1694 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001695}
1696
1697static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1698{
1699 struct stream_out *out = (struct stream_out *)stream;
1700
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001701 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702}
1703
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301704static int out_set_sample_rate(struct audio_stream *stream __unused,
1705 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001706{
1707 return -ENOSYS;
1708}
1709
1710static size_t out_get_buffer_size(const struct audio_stream *stream)
1711{
1712 struct stream_out *out = (struct stream_out *)stream;
1713
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001714 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001715 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001716 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1717 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001718
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301719 return out->config.period_size *
1720 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001721}
1722
1723static uint32_t out_get_channels(const struct audio_stream *stream)
1724{
1725 struct stream_out *out = (struct stream_out *)stream;
1726
1727 return out->channel_mask;
1728}
1729
1730static audio_format_t out_get_format(const struct audio_stream *stream)
1731{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001732 struct stream_out *out = (struct stream_out *)stream;
1733
1734 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001735}
1736
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301737static int out_set_format(struct audio_stream *stream __unused,
1738 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001739{
1740 return -ENOSYS;
1741}
1742
1743static int out_standby(struct audio_stream *stream)
1744{
1745 struct stream_out *out = (struct stream_out *)stream;
1746 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001747
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301748 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1749 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001750 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1751 /* Ignore standby in case of voip call because the voip output
1752 * stream is closed in adev_close_output_stream()
1753 */
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301754 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001755 return 0;
1756 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001757
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001758 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001759 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001760 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07001761
1762 amplifier_output_stream_standby((struct audio_stream_out *) stream);
1763
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001764 out->standby = true;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001765 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001766 if (out->pcm) {
1767 pcm_close(out->pcm);
1768 out->pcm = NULL;
1769 }
1770 } else {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301771 ALOGD("copl(%x):standby", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001772 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001773 out->gapless_mdata.encoder_delay = 0;
1774 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001775 if (out->compr != NULL) {
1776 compress_close(out->compr);
1777 out->compr = NULL;
1778 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001779 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001780 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001781 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782 }
1783 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001784 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001785 return 0;
1786}
1787
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301788static int out_dump(const struct audio_stream *stream __unused,
1789 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001790{
1791 return 0;
1792}
1793
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001794static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1795{
1796 int ret = 0;
1797 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001798 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001799 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001800 tmp_mdata.encoder_delay = 0;
1801 tmp_mdata.encoder_padding = 0;
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001802
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001803 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001804 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001805 return -EINVAL;
1806 }
1807
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001808 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1809 if (ret >= 0) {
1810 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1811 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1812 ALOGV("ADTS format is set in offload mode");
1813 }
1814 out->send_new_metadata = 1;
1815 }
1816
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001817#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001818 if (out->format == AUDIO_FORMAT_FLAC) {
1819 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1820 if (ret >= 0) {
1821 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1822 out->send_new_metadata = 1;
1823 }
1824 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1825 if (ret >= 0) {
1826 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1827 out->send_new_metadata = 1;
1828 }
1829 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1830 if (ret >= 0) {
1831 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1832 out->send_new_metadata = 1;
1833 }
1834 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1835 if (ret >= 0) {
1836 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1837 out->send_new_metadata = 1;
1838 }
1839 }
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001840#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001841
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001842 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1843 if(ret >= 0)
1844 is_meta_data_params = true;
1845 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1846 if(ret >= 0 )
1847 is_meta_data_params = true;
1848 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1849 if(ret >= 0 )
1850 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001851 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1852 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001853 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001854 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001855 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001856 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1857 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001858 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001859 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860 }
1861
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001862 if(!is_meta_data_params) {
1863 ALOGV("%s: Not gapless meta data params", __func__);
1864 return 0;
1865 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001866 out->gapless_mdata = tmp_mdata;
1867 out->send_new_metadata = 1;
1868 ALOGV("%s new encoder delay %u and padding %u", __func__,
1869 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1870
Steve Kondikba3b35d2014-07-18 01:49:48 -07001871 if(out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
1872 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
1873 if (ret >= 0) {
1874 out->compr_config.codec->format = atoi(value);
1875 }
1876 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
1877 if (ret >= 0) {
1878 out->compr_config.codec->options.wma.super_block_align = atoi(value);
1879 }
1880 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
1881 if (ret >= 0) {
1882 out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
1883 }
1884 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
1885 if (ret >= 0) {
1886 out->compr_config.codec->options.wma.channelmask = atoi(value);
1887 }
1888 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
1889 if (ret >= 0) {
1890 out->compr_config.codec->options.wma.encodeopt = atoi(value);
1891 }
1892 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
1893 if (ret >= 0) {
1894 out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
1895 }
1896 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
1897 if (ret >= 0) {
1898 out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
1899 }
1900 ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
1901 out->compr_config.codec->format,
1902 out->compr_config.codec->options.wma.super_block_align,
1903 out->compr_config.codec->options.wma.bits_per_sample,
1904 out->compr_config.codec->options.wma.channelmask,
1905 out->compr_config.codec->options.wma.encodeopt,
1906 out->compr_config.codec->options.wma.encodeopt1,
1907 out->compr_config.codec->options.wma.encodeopt2);
1908 }
1909
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001910 return 0;
1911}
1912
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301913static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1914{
1915 return out == adev->primary_output || out == adev->voice_tx_output;
1916}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001918static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1919{
1920 struct stream_out *out = (struct stream_out *)stream;
1921 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001922 struct audio_usecase *usecase;
1923 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924 struct str_parms *parms;
1925 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001926 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001927 bool select_new_device = false;
Steve Kondik3abbbc82014-11-29 14:14:43 -08001928 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001929
sangwoobc677242013-08-08 16:53:43 +09001930 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001931 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001932 parms = str_parms_create_str(kvpairs);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001933 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1934 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001936 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001937 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001939 /*
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301940 * When HDMI cable is unplugged/usb hs is disconnected the
1941 * music playback is paused and the policy manager sends routing=0
1942 * But the audioflingercontinues to write data until standby time
1943 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001944 * Avoid this by routing audio to speaker until standby.
1945 */
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301946 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
Steve Kondikeadb6c82014-09-03 18:40:06 -07001947 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
1948 out->devices == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001949 val == AUDIO_DEVICE_NONE) {
1950 val = AUDIO_DEVICE_OUT_SPEAKER;
1951 }
1952
1953 /*
1954 * select_devices() call below switches all the usecases on the same
1955 * backend to the new device. Refer to check_usecases_codec_backend() in
1956 * the select_devices(). But how do we undo this?
1957 *
1958 * For example, music playback is active on headset (deep-buffer usecase)
1959 * and if we go to ringtones and select a ringtone, low-latency usecase
1960 * will be started on headset+speaker. As we can't enable headset+speaker
1961 * and headset devices at the same time, select_devices() switches the music
1962 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1963 * So when the ringtone playback is completed, how do we undo the same?
1964 *
1965 * We are relying on the out_set_parameters() call on deep-buffer output,
1966 * once the ringtone playback is ended.
1967 * NOTE: We should not check if the current devices are same as new devices.
1968 * Because select_devices() must be called to switch back the music
1969 * playback to headset.
1970 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001971 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001972 out->devices = val;
1973
1974 if (!out->standby)
1975 select_devices(adev, out->usecase);
1976
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001977 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301978 output_drives_call(adev, out)) {
1979 adev->current_call_output = out;
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001980 if (!adev->voice.in_call)
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301981 ret = voice_start_call(adev);
1982 else
1983 voice_update_devices_for_all_voice_usecases(adev);
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001984 }
1985 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001986
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001987 if ((adev->mode == AUDIO_MODE_NORMAL) &&
1988 adev->voice.in_call &&
1989 output_drives_call(adev, out)) {
1990 ret = voice_stop_call(adev);
1991 adev->current_call_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001992 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001993
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001994 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001995 pthread_mutex_unlock(&out->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05001996
1997 /*handles device and call state changes*/
1998 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002000
2001 if (out == adev->primary_output) {
2002 pthread_mutex_lock(&adev->lock);
2003 audio_extn_set_parameters(adev, parms);
2004 pthread_mutex_unlock(&adev->lock);
2005 }
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002006 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002007 pthread_mutex_lock(&out->lock);
Steve Kondikba3b35d2014-07-18 01:49:48 -07002008 ret = parse_compress_metadata(out, parms);
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002009 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002010 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002011
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002012 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002013 ALOGV("%s: exit: code(%d)", __func__, status);
2014 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002015}
2016
2017static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2018{
2019 struct stream_out *out = (struct stream_out *)stream;
2020 struct str_parms *query = str_parms_create_str(keys);
2021 char *str;
2022 char value[256];
2023 struct str_parms *reply = str_parms_create();
2024 size_t i, j;
2025 int ret;
2026 bool first = true;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002027
2028 if (!query || !reply) {
2029 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2030 return NULL;
2031 }
2032
Eric Laurent994a6932013-07-17 11:51:42 -07002033 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002034 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2035 if (ret >= 0) {
2036 value[0] = '\0';
2037 i = 0;
2038 while (out->supported_channel_masks[i] != 0) {
2039 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2040 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2041 if (!first) {
2042 strcat(value, "|");
2043 }
2044 strcat(value, out_channels_name_to_enum_table[j].name);
2045 first = false;
2046 break;
2047 }
2048 }
2049 i++;
2050 }
2051 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2052 str = str_parms_to_str(reply);
2053 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002054 voice_extn_out_get_parameters(out, query, reply);
2055 str = str_parms_to_str(reply);
2056 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella2e032352014-01-29 12:52:19 -08002057 free(str);
2058 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002059 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002060 }
2061 str_parms_destroy(query);
2062 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002063 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064 return str;
2065}
2066
2067static uint32_t out_get_latency(const struct audio_stream_out *stream)
2068{
2069 struct stream_out *out = (struct stream_out *)stream;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002070 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002071
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002072 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002073 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002074 } else {
2075 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002076 (out->config.rate);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002077 }
2078
Anish Kumar1a0594f2014-12-09 04:01:39 +05302079 ALOGV("%s: Latency %d", __func__, latency);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002080 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002081}
2082
2083static int out_set_volume(struct audio_stream_out *stream, float left,
2084 float right)
2085{
Eric Laurenta9024de2013-04-04 09:19:12 -07002086 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002087 int volume[2];
2088
Eric Laurenta9024de2013-04-04 09:19:12 -07002089 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2090 /* only take left channel into account: the API is for stereo anyway */
2091 out->muted = (left == 0.0f);
2092 return 0;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002093 } else if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002094 char mixer_ctl_name[128];
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002095 struct audio_device *adev = out->dev;
2096 struct mixer_ctl *ctl;
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002097 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2098 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002099
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002100 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2101 "Compress Playback %d Volume", pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002102 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2103 if (!ctl) {
2104 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2105 __func__, mixer_ctl_name);
2106 return -EINVAL;
2107 }
2108 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2109 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2110 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2111 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002112 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002114 return -ENOSYS;
2115}
2116
2117static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2118 size_t bytes)
2119{
2120 struct stream_out *out = (struct stream_out *)stream;
2121 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302122 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002123 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002124
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002125 pthread_mutex_lock(&out->lock);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302126
Naresh Tannirucef332d2014-06-04 18:17:56 +05302127 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
2128 if (out->pcm) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302129 ALOGD(" %s: sound card is not active/SSR state", __func__);
2130 ret= -ENETRESET;
2131 goto exit;
Alexy Joseph55204352014-10-06 12:15:01 -07002132 } else if (is_offload_usecase(out->usecase)) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302133 //during SSR for compress usecase we should return error to flinger
2134 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2135 pthread_mutex_unlock(&out->lock);
2136 return -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302137 }
2138 }
2139
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002140 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002141 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002142 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002143 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2144 ret = voice_extn_compress_voip_start_output_stream(out);
2145 else
2146 ret = start_output_stream(out);
Ethan Chen79c356c2015-06-07 12:26:14 -07002147
2148 if (ret == 0)
2149 amplifier_output_stream_start(stream,
2150 is_offload_usecase(out->usecase));
2151
Eric Laurent150dbfe2013-02-27 14:31:02 -08002152 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002153 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002154 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002155 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156 goto exit;
2157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002160 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002161 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002162 if (out->send_new_metadata) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302163 ALOGD("copl(%x):send new gapless metadata", (unsigned int)out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002164 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2165 out->send_new_metadata = 0;
2166 }
2167
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002168 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302169 if (ret < 0)
2170 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002171 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002172 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302173 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302175 } else if (-ENETRESET == ret) {
2176 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2177 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2178 pthread_mutex_unlock(&out->lock);
2179 out_standby(&out->stream.common);
2180 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002181 }
Naresh Tannirucef332d2014-06-04 18:17:56 +05302182 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002183 compress_start(out->compr);
2184 out->playback_started = 1;
2185 out->offload_state = OFFLOAD_STATE_PLAYING;
2186 }
2187 pthread_mutex_unlock(&out->lock);
2188 return ret;
2189 } else {
2190 if (out->pcm) {
2191 if (out->muted)
2192 memset((void *)buffer, 0, bytes);
2193 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302194 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2195 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2196 else
2197 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302198 if (ret < 0)
2199 ret = -errno;
2200 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002201 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002202 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002203 }
2204
2205exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302206 /* ToDo: There may be a corner case when SSR happens back to back during
2207 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302208 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302209 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302210 }
2211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002212 pthread_mutex_unlock(&out->lock);
2213
2214 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002215 if (out->pcm)
2216 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302217 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302218 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302219 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302220 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302221 out->standby = true;
2222 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223 out_standby(&out->stream.common);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002224 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
2225 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226 }
2227 return bytes;
2228}
2229
2230static int out_get_render_position(const struct audio_stream_out *stream,
2231 uint32_t *dsp_frames)
2232{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002233 struct stream_out *out = (struct stream_out *)stream;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002234 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
2235 ssize_t ret = 0;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002236 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002237 pthread_mutex_lock(&out->lock);
2238 if (out->compr != NULL) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302239 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002240 &out->sample_rate);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302241 if (ret < 0)
2242 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002243 ALOGVV("%s rendered frames %d sample_rate %d",
2244 __func__, *dsp_frames, out->sample_rate);
2245 }
2246 pthread_mutex_unlock(&out->lock);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302247 if (-ENETRESET == ret) {
2248 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2249 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2250 return -EINVAL;
2251 } else if(ret < 0) {
Steve Kondik81506242014-07-21 16:12:57 -07002252 if (out->compr == NULL) {
2253 return 0;
2254 }
2255 ALOGE(" ERROR: Unable to get time stamp from compress driver ret=%d", ret);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302256 return -EINVAL;
2257 } else {
2258 return 0;
2259 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002260 } else
2261 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262}
2263
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302264static int out_add_audio_effect(const struct audio_stream *stream __unused,
2265 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266{
2267 return 0;
2268}
2269
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302270static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2271 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272{
2273 return 0;
2274}
2275
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302276static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2277 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278{
2279 return -EINVAL;
2280}
2281
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002282static int out_get_presentation_position(const struct audio_stream_out *stream,
2283 uint64_t *frames, struct timespec *timestamp)
2284{
2285 struct stream_out *out = (struct stream_out *)stream;
2286 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002287 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002288
2289 pthread_mutex_lock(&out->lock);
2290
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002291 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002292 if (out->compr != NULL) {
2293 compress_get_tstamp(out->compr, &dsp_frames,
2294 &out->sample_rate);
2295 ALOGVV("%s rendered frames %ld sample_rate %d",
2296 __func__, dsp_frames, out->sample_rate);
2297 *frames = dsp_frames;
2298 ret = 0;
2299 /* this is the best we can do */
2300 clock_gettime(CLOCK_MONOTONIC, timestamp);
2301 }
2302 } else {
2303 if (out->pcm) {
2304 size_t avail;
2305 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2306 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002307 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002308 // This adjustment accounts for buffering after app processor.
2309 // It is based on estimated DSP latency per use case, rather than exact.
2310 signed_frames -=
2311 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2312
Eric Laurent949a0892013-09-20 09:20:13 -07002313 // It would be unusual for this value to be negative, but check just in case ...
2314 if (signed_frames >= 0) {
2315 *frames = signed_frames;
2316 ret = 0;
2317 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002318 }
2319 }
2320 }
2321
2322 pthread_mutex_unlock(&out->lock);
2323
2324 return ret;
2325}
2326
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002327static int out_set_callback(struct audio_stream_out *stream,
2328 stream_callback_t callback, void *cookie)
2329{
2330 struct stream_out *out = (struct stream_out *)stream;
2331
2332 ALOGV("%s", __func__);
2333 pthread_mutex_lock(&out->lock);
2334 out->offload_callback = callback;
2335 out->offload_cookie = cookie;
2336 pthread_mutex_unlock(&out->lock);
2337 return 0;
2338}
2339
2340static int out_pause(struct audio_stream_out* stream)
2341{
2342 struct stream_out *out = (struct stream_out *)stream;
2343 int status = -ENOSYS;
2344 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002345 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302346 ALOGD("copl(%x):pause compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002347 pthread_mutex_lock(&out->lock);
2348 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302349 struct audio_device *adev = out->dev;
2350 int snd_scard_state = get_snd_card_state(adev);
2351
2352 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2353 status = compress_pause(out->compr);
2354
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002355 out->offload_state = OFFLOAD_STATE_PAUSED;
2356 }
2357 pthread_mutex_unlock(&out->lock);
2358 }
2359 return status;
2360}
2361
2362static int out_resume(struct audio_stream_out* stream)
2363{
2364 struct stream_out *out = (struct stream_out *)stream;
2365 int status = -ENOSYS;
2366 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002367 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302368 ALOGD("copl(%x):resume compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002369 status = 0;
2370 pthread_mutex_lock(&out->lock);
2371 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302372 struct audio_device *adev = out->dev;
2373 int snd_scard_state = get_snd_card_state(adev);
2374
2375 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2376 status = compress_resume(out->compr);
2377
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002378 out->offload_state = OFFLOAD_STATE_PLAYING;
2379 }
2380 pthread_mutex_unlock(&out->lock);
2381 }
2382 return status;
2383}
2384
2385static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2386{
2387 struct stream_out *out = (struct stream_out *)stream;
2388 int status = -ENOSYS;
2389 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002390 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002391 pthread_mutex_lock(&out->lock);
2392 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2393 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2394 else
2395 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2396 pthread_mutex_unlock(&out->lock);
2397 }
2398 return status;
2399}
2400
2401static int out_flush(struct audio_stream_out* stream)
2402{
2403 struct stream_out *out = (struct stream_out *)stream;
2404 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002405 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302406 ALOGD("copl(%x):calling compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002407 pthread_mutex_lock(&out->lock);
2408 stop_compressed_output_l(out);
2409 pthread_mutex_unlock(&out->lock);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302410 ALOGD("copl(%x):out of compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002411 return 0;
2412 }
2413 return -ENOSYS;
2414}
2415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002416/** audio_stream_in implementation **/
2417static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2418{
2419 struct stream_in *in = (struct stream_in *)stream;
2420
2421 return in->config.rate;
2422}
2423
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302424static int in_set_sample_rate(struct audio_stream *stream __unused,
2425 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002426{
2427 return -ENOSYS;
2428}
2429
2430static size_t in_get_buffer_size(const struct audio_stream *stream)
2431{
2432 struct stream_in *in = (struct stream_in *)stream;
2433
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002434 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2435 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002436 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2437 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002438
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302439 return in->config.period_size *
Steve Kondik3abbbc82014-11-29 14:14:43 -08002440 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002441}
2442
2443static uint32_t in_get_channels(const struct audio_stream *stream)
2444{
2445 struct stream_in *in = (struct stream_in *)stream;
2446
2447 return in->channel_mask;
2448}
2449
2450static audio_format_t in_get_format(const struct audio_stream *stream)
2451{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002452 struct stream_in *in = (struct stream_in *)stream;
2453
2454 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455}
2456
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302457static int in_set_format(struct audio_stream *stream __unused,
2458 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002459{
2460 return -ENOSYS;
2461}
2462
2463static int in_standby(struct audio_stream *stream)
2464{
2465 struct stream_in *in = (struct stream_in *)stream;
2466 struct audio_device *adev = in->dev;
2467 int status = 0;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302468 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2469 stream, in->usecase, use_case_table[in->usecase]);
2470
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002471
2472 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2473 /* Ignore standby in case of voip call because the voip input
2474 * stream is closed in adev_close_input_stream()
2475 */
2476 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2477 return status;
2478 }
2479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002480 pthread_mutex_lock(&in->lock);
2481 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002482 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07002483
2484 amplifier_input_stream_standby((struct audio_stream_in *) stream);
2485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002487 if (in->pcm) {
2488 pcm_close(in->pcm);
2489 in->pcm = NULL;
2490 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002492 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002493 }
2494 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002495 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002496 return status;
2497}
2498
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302499static int in_dump(const struct audio_stream *stream __unused,
2500 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002501{
2502 return 0;
2503}
2504
2505static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2506{
2507 struct stream_in *in = (struct stream_in *)stream;
2508 struct audio_device *adev = in->dev;
2509 struct str_parms *parms;
2510 char *str;
2511 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002512 int ret = 0, val = 0, err;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002513 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302515 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 parms = str_parms_create_str(kvpairs);
2517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002519 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002520
2521 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2522 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002523 val = atoi(value);
2524 /* no audio source uses val == 0 */
2525 if ((in->source != val) && (val != 0)) {
2526 in->source = val;
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002527 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2528 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2529 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2530 (in->config.rate == 8000 || in->config.rate == 16000) &&
Steve Kondikb6ab1fa2015-02-06 16:55:26 -08002531 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002532 err = voice_extn_compress_voip_open_input_stream(in);
2533 if (err != 0) {
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002534 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002535 __func__, err);
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002536 }
2537 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 }
2539 }
2540
Steve Kondik3abbbc82014-11-29 14:14:43 -08002541 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2542
2543 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 val = atoi(value);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302545 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546 in->device = val;
2547 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002548 if (!in->standby)
Steve Kondik3abbbc82014-11-29 14:14:43 -08002549 status = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550 }
2551 }
2552
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002553done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002554 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002555 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556
2557 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002558 ALOGV("%s: exit: status(%d)", __func__, status);
2559 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560}
2561
2562static char* in_get_parameters(const struct audio_stream *stream,
2563 const char *keys)
2564{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002565 struct stream_in *in = (struct stream_in *)stream;
2566 struct str_parms *query = str_parms_create_str(keys);
2567 char *str;
2568 char value[256];
2569 struct str_parms *reply = str_parms_create();
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002570
2571 if (!query || !reply) {
2572 ALOGE("in_get_parameters: failed to create query or reply");
2573 return NULL;
2574 }
2575
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002576 ALOGV("%s: enter: keys - %s", __func__, keys);
2577
2578 voice_extn_in_get_parameters(in, query, reply);
2579
2580 str = str_parms_to_str(reply);
2581 str_parms_destroy(query);
2582 str_parms_destroy(reply);
2583
2584 ALOGV("%s: exit: returns - %s", __func__, str);
2585 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586}
2587
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302588static int in_set_gain(struct audio_stream_in *stream __unused,
2589 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590{
2591 return 0;
2592}
2593
2594static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2595 size_t bytes)
2596{
2597 struct stream_in *in = (struct stream_in *)stream;
2598 struct audio_device *adev = in->dev;
2599 int i, ret = -1;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302600 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002602 pthread_mutex_lock(&in->lock);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302603
2604 if (in->pcm) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302605 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302606 ALOGD(" %s: sound card is not active/SSR state", __func__);
2607 ret= -ENETRESET;
2608 goto exit;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302609 }
2610 }
2611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002613 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002614 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2615 ret = voice_extn_compress_voip_start_input_stream(in);
2616 else
2617 ret = start_input_stream(in);
Ethan Chen79c356c2015-06-07 12:26:14 -07002618
2619 if (ret == 0)
2620 amplifier_input_stream_start(stream);
2621
Eric Laurent150dbfe2013-02-27 14:31:02 -08002622 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002623 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002624 goto exit;
2625 }
2626 in->standby = 0;
2627 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002628
2629 if (in->pcm) {
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302630 if (audio_extn_ssr_get_enabled() &&
2631 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002632 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002633 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2634 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302635 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2636 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002637 else
2638 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302639 if (ret < 0)
2640 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641 }
2642
2643 /*
2644 * Instead of writing zeroes here, we could trust the hardware
2645 * to always provide zeroes when muted.
2646 */
Pavan Chikkala6c183fd2014-12-04 10:48:28 +05302647 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2648 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 memset(buffer, 0, bytes);
2650
2651exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302652 /* ToDo: There may be a corner case when SSR happens back to back during
2653 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302654 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302655 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302656 memset(buffer, 0, bytes);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302657 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002658 pthread_mutex_unlock(&in->lock);
2659
2660 if (ret != 0) {
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302661 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302662 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302663 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302664 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302665 in->standby = true;
2666 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002667 in_standby(&in->stream.common);
2668 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002669 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
2670 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671 }
2672 return bytes;
2673}
2674
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302675static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676{
2677 return 0;
2678}
2679
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002680static int add_remove_audio_effect(const struct audio_stream *stream,
2681 effect_handle_t effect,
2682 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002683{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002684 struct stream_in *in = (struct stream_in *)stream;
2685 int status = 0;
2686 effect_descriptor_t desc;
2687
2688 status = (*effect)->get_descriptor(effect, &desc);
2689 if (status != 0)
2690 return status;
2691
2692 pthread_mutex_lock(&in->lock);
2693 pthread_mutex_lock(&in->dev->lock);
2694 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2695 in->enable_aec != enable &&
2696 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2697 in->enable_aec = enable;
2698 if (!in->standby)
2699 select_devices(in->dev, in->usecase);
2700 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002701 if (in->enable_ns != enable &&
2702 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2703 in->enable_ns = enable;
2704 if (!in->standby)
2705 select_devices(in->dev, in->usecase);
2706 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002707 pthread_mutex_unlock(&in->dev->lock);
2708 pthread_mutex_unlock(&in->lock);
2709
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 return 0;
2711}
2712
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002713static int in_add_audio_effect(const struct audio_stream *stream,
2714 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715{
Eric Laurent994a6932013-07-17 11:51:42 -07002716 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002717 return add_remove_audio_effect(stream, effect, true);
2718}
2719
2720static int in_remove_audio_effect(const struct audio_stream *stream,
2721 effect_handle_t effect)
2722{
Eric Laurent994a6932013-07-17 11:51:42 -07002723 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002724 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725}
2726
2727static int adev_open_output_stream(struct audio_hw_device *dev,
2728 audio_io_handle_t handle,
2729 audio_devices_t devices,
2730 audio_output_flags_t flags,
2731 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302732 struct audio_stream_out **stream_out,
2733 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002734{
2735 struct audio_device *adev = (struct audio_device *)dev;
2736 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002737 int i, ret = 0;
Steve Kondik5a447012014-12-02 16:04:20 -08002738 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002739
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740 *stream_out = NULL;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302741
2742 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2743 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2744 ALOGE(" sound card is not active rejecting compress output open request");
2745 return -EINVAL;
2746 }
2747
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002748 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2749
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302750 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2751 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2752 devices, flags, &out->stream);
2753
2754
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002755 if (!out) {
2756 return -ENOMEM;
2757 }
2758
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002759 if (devices == AUDIO_DEVICE_NONE)
2760 devices = AUDIO_DEVICE_OUT_SPEAKER;
2761
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 out->flags = flags;
2763 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002764 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002765 out->format = config->format;
2766 out->sample_rate = config->sample_rate;
2767 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2768 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002769 out->handle = handle;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002770 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002771 out->non_blocking = 0;
2772 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002773
2774 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002775 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
Mingming Yinee733602014-04-03 17:47:22 -07002776 (
2777#ifdef AFE_PROXY_ENABLED
2778 out->devices & AUDIO_DEVICE_OUT_PROXY ||
2779#endif
2780 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002781
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002782 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002783 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2784 ret = read_hdmi_channel_masks(out);
2785
Mingming Yinee733602014-04-03 17:47:22 -07002786#ifdef AFE_PROXY_ENABLED
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002787 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2788 ret = audio_extn_read_afe_proxy_channel_masks(out);
Mingming Yinee733602014-04-03 17:47:22 -07002789#endif
2790
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002791 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002792 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002793 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002794
2795 if (config->sample_rate == 0)
2796 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2797 if (config->channel_mask == 0)
2798 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2799
2800 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002801 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002802 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2803 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804 out->config.rate = config->sample_rate;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302805 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002806 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Mingming Yinee733602014-04-03 17:47:22 -07002807#ifdef COMPRESS_VOIP_ENABLED
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002808 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2809 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002810 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002811 ret = voice_extn_compress_voip_open_output_stream(out);
2812 if (ret != 0) {
2813 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2814 __func__, ret);
2815 goto error_open;
2816 }
Mingming Yinee733602014-04-03 17:47:22 -07002817#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302819 ALOGD("%s: copl(%x): sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
2820 __func__, (unsigned int)out, config->sample_rate, config->channel_mask, devices, flags);
2821
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002822 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2823 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2824 ALOGE("%s: Unsupported Offload information", __func__);
2825 ret = -EINVAL;
2826 goto error_open;
2827 }
Mingming Yin90310102013-11-13 16:57:00 -08002828 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002829 !audio_extn_is_dolby_format(config->offload_info.format)) {
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002830 ALOGE("%s: Unsupported offload audio format %x", __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002831 ret = -EINVAL;
2832 goto error_open;
2833 }
2834
2835 out->compr_config.codec = (struct snd_codec *)
2836 calloc(1, sizeof(struct snd_codec));
2837
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002838 if (!out->compr_config.codec) {
2839 ret = -ENOMEM;
2840 goto error_open;
2841 }
2842
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002843 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002844 if (config->offload_info.channel_mask)
2845 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002846 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847 out->channel_mask = config->channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002848 config->offload_info.channel_mask = config->channel_mask;
2849 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002850 out->format = config->offload_info.format;
2851 out->sample_rate = config->offload_info.sample_rate;
2852
2853 out->stream.set_callback = out_set_callback;
2854 out->stream.pause = out_pause;
2855 out->stream.resume = out_resume;
2856 out->stream.drain = out_drain;
2857 out->stream.flush = out_flush;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002858 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002859
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002860 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002861 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002862 audio_extn_dolby_get_snd_codec_id(adev, out,
2863 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002864 else
2865 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002866 get_snd_codec_id(config->offload_info.format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002867
ApurupaPattapu0c566872014-01-10 14:46:02 -08002868 if (audio_is_offload_pcm(config->offload_info.format)) {
2869 out->compr_config.fragment_size =
2870 platform_get_pcm_offload_buffer_size(&config->offload_info);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002871 } else {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002872 out->compr_config.fragment_size =
2873 platform_get_compress_offload_buffer_size(&config->offload_info);
2874 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002875 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0043e152014-10-23 14:42:59 -07002876#ifdef NEW_SAMPLE_RATE_ENABLED
2877 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
2878#else
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002879 out->compr_config.codec->sample_rate =
2880 compress_get_alsa_rate(config->offload_info.sample_rate);
Eric Laurent0043e152014-10-23 14:42:59 -07002881#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 out->compr_config.codec->bit_rate =
2883 config->offload_info.bit_rate;
2884 out->compr_config.codec->ch_in =
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302885 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002887 out->bit_width = config->offload_info.bit_width;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002889 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
Steve Kondik37454012014-11-23 19:54:21 -08002890 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002891 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2892 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002893
Steve Kondik3abbbc82014-11-29 14:14:43 -08002894 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002895 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002896
Steve Kondik3abbbc82014-11-29 14:14:43 -08002897 if (out->bit_width == 24)
2898 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002899
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002900#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik37454012014-11-23 19:54:21 -08002901 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
2902 out->compr_config.codec->options.flac_dec.sample_size = config->offload_info.bit_width;
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002903#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002904
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002905 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2906 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002907
Mingming Yind48310a2015-06-10 16:28:10 -07002908 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002909 //this flag is set from framework only if its for PCM formats
2910 //no need to check for PCM format again
2911 out->non_blocking = 0;
2912 out->use_small_bufs = true;
2913 ALOGI("Keep write blocking for small buff: non_blockling %d",
2914 out->non_blocking);
2915 }
2916
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002917 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002918 out->offload_state = OFFLOAD_STATE_IDLE;
2919 out->playback_started = 0;
2920
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002921 create_offload_callback_thread(out);
2922 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2923 __func__, config->offload_info.version,
2924 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002925 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -08002926 check_and_set_gapless_mode(adev);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002927
Mingming Yinee733602014-04-03 17:47:22 -07002928#ifdef INCALL_MUSIC_ENABLED
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002929 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2930 ret = voice_check_and_set_incall_music_usecase(adev, out);
2931 if (ret != 0) {
2932 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2933 __func__, ret);
2934 goto error_open;
2935 }
Mingming Yinee733602014-04-03 17:47:22 -07002936#endif
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302937 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2938 if (config->sample_rate == 0)
2939 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2940 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2941 config->sample_rate != 8000) {
2942 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2943 ret = -EINVAL;
2944 goto error_open;
2945 }
2946 out->sample_rate = config->sample_rate;
2947 out->config.rate = config->sample_rate;
2948 if (config->format == AUDIO_FORMAT_DEFAULT)
2949 config->format = AUDIO_FORMAT_PCM_16_BIT;
2950 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2951 config->format = AUDIO_FORMAT_PCM_16_BIT;
2952 ret = -EINVAL;
2953 goto error_open;
2954 }
2955 out->format = config->format;
2956 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2957 out->config = pcm_config_afe_proxy_playback;
2958 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002959 } else {
Steve Kondik3abbbc82014-11-29 14:14:43 -08002960#ifndef LOW_LATENCY_PRIMARY
2961 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
2962 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2963 out->config = pcm_config_low_latency;
Steve Kondikb045f472014-11-12 23:24:07 -08002964#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -08002965#ifdef LOW_LATENCY_PRIMARY
2966 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2967 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2968 out->config = pcm_config_deep_buffer;
2969#endif
2970 } else {
2971 /* primary path is the default path selected if no other outputs are available/suitable */
2972 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
2973#ifdef LOW_LATENCY_PRIMARY
2974 out->config = pcm_config_low_latency;
2975#else
2976 out->config = pcm_config_deep_buffer;
2977#endif
2978 }
2979 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2980 if (k_enable_extended_precision
2981 && pcm_params_format_test(adev->use_case_table[out->usecase],
2982 pcm_format_from_audio_format(config->format))) {
2983 out->config.format = pcm_format_from_audio_format(config->format);
2984 /* out->format already set to config->format */
2985 } else {
2986 /* deny the externally proposed config format
2987 * and use the one specified in audio_hw layer configuration.
2988 * Note: out->format is returned by out->stream.common.get_format()
2989 * and is used to set config->format in the code several lines below.
2990 */
Steve Kondik5a447012014-12-02 16:04:20 -08002991 ALOGW("Audio format %x is not available on this output", out->format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002992 out->format = audio_format_from_pcm_format(out->config.format);
2993 }
2994 }
2995
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002996 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002997 }
2998
Steve Kondik5a447012014-12-02 16:04:20 -08002999 ALOGV("%s flags %x, format %x, sample_rate %d, out->bit_width %d",
3000 __func__, flags, out->format, out->sample_rate, out->bit_width);
3001
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003002 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
Steve Kondik3abbbc82014-11-29 14:14:43 -08003003 flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003004 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003005 if(adev->primary_output == NULL)
3006 adev->primary_output = out;
3007 else {
3008 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003009 ret = -EEXIST;
3010 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003011 }
3012 }
3013
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014 /* Check if this usecase is already existing */
3015 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella0d06c8e2014-04-17 20:00:41 -07003016 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3017 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003019 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003020 ret = -EEXIST;
3021 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 }
3023 pthread_mutex_unlock(&adev->lock);
3024
3025 out->stream.common.get_sample_rate = out_get_sample_rate;
3026 out->stream.common.set_sample_rate = out_set_sample_rate;
3027 out->stream.common.get_buffer_size = out_get_buffer_size;
3028 out->stream.common.get_channels = out_get_channels;
3029 out->stream.common.get_format = out_get_format;
3030 out->stream.common.set_format = out_set_format;
3031 out->stream.common.standby = out_standby;
3032 out->stream.common.dump = out_dump;
3033 out->stream.common.set_parameters = out_set_parameters;
3034 out->stream.common.get_parameters = out_get_parameters;
3035 out->stream.common.add_audio_effect = out_add_audio_effect;
3036 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3037 out->stream.get_latency = out_get_latency;
3038 out->stream.set_volume = out_set_volume;
3039 out->stream.write = out_write;
3040 out->stream.get_render_position = out_get_render_position;
3041 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003042 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003044 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003045 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003046 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003047
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303048 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3049 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3050
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051 config->format = out->stream.common.get_format(&out->stream.common);
3052 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3053 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3054
3055 *stream_out = &out->stream;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303056 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3057 use_case_table[out->usecase]);
Eric Laurent994a6932013-07-17 11:51:42 -07003058 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003059 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003060
3061error_open:
3062 free(out);
3063 *stream_out = NULL;
3064 ALOGD("%s: exit: ret %d", __func__, ret);
3065 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066}
3067
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303068static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 struct audio_stream_out *stream)
3070{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003071 struct stream_out *out = (struct stream_out *)stream;
3072 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003073 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003074
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303075 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3076
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003077 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303078 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003079 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303080 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003081 if(ret != 0)
3082 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3083 __func__, ret);
3084 }
3085 else
3086 out_standby(&stream->common);
3087
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003088 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003090 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003091 if (out->compr_config.codec != NULL)
3092 free(out->compr_config.codec);
3093 }
3094 pthread_cond_destroy(&out->cond);
3095 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003097 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098}
3099
Alexy Joseph55204352014-10-06 12:15:01 -07003100static void close_compress_sessions(struct audio_device *adev)
3101{
3102 struct stream_out *out = NULL;
3103 struct listnode *node = NULL;
3104 struct listnode *tmp = NULL;
3105 struct audio_usecase *usecase = NULL;
3106 pthread_mutex_lock(&adev->lock);
3107 list_for_each_safe(node, tmp, &adev->usecase_list) {
3108 usecase = node_to_item(node, struct audio_usecase, list);
3109 if (is_offload_usecase(usecase->id)) {
3110 if (usecase && usecase->stream.out) {
3111 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3112 out = usecase->stream.out;
3113 pthread_mutex_unlock(&adev->lock);
3114 out_standby(&out->stream.common);
3115 pthread_mutex_lock(&adev->lock);
3116 }
3117 }
3118 }
3119 pthread_mutex_unlock(&adev->lock);
3120}
3121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003122static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3123{
3124 struct audio_device *adev = (struct audio_device *)dev;
3125 struct str_parms *parms;
3126 char *str;
3127 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003128 int val;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303129 int ret;
3130 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003131
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003132 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003133 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303135 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3136 if (ret >= 0) {
3137 char *snd_card_status = value+2;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303138 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05303139 struct listnode *node;
3140 struct audio_usecase *usecase;
3141
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303142 ALOGD("Received sound card OFFLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303143 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3144
Alexy Joseph55204352014-10-06 12:15:01 -07003145 //close compress sessions on OFFLINE status
3146 close_compress_sessions(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303147 } else if (strstr(snd_card_status, "ONLINE")) {
3148 ALOGD("Received sound card ONLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303149 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303150 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303151 }
3152
3153 pthread_mutex_lock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303154 status = voice_set_parameters(adev, parms);
3155 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003156 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003157
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303158 status = platform_set_parameters(adev->platform, parms);
3159 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003160 goto done;
3161
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303162 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3163 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003164 /* When set to false, HAL should disable EC and NS
3165 * But it is currently not supported.
3166 */
3167 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3168 adev->bluetooth_nrec = true;
3169 else
3170 adev->bluetooth_nrec = false;
3171 }
3172
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303173 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3174 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003175 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3176 adev->screen_off = false;
3177 else
3178 adev->screen_off = true;
3179 }
3180
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303181 ret = str_parms_get_int(parms, "rotation", &val);
3182 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003183 bool reverse_speakers = false;
3184 switch(val) {
3185 // FIXME: note that the code below assumes that the speakers are in the correct placement
3186 // relative to the user when the device is rotated 90deg from its default rotation. This
3187 // assumption is device-specific, not platform-specific like this code.
3188 case 270:
3189 reverse_speakers = true;
3190 break;
3191 case 0:
3192 case 90:
3193 case 180:
3194 break;
3195 default:
3196 ALOGE("%s: unexpected rotation of %d", __func__, val);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303197 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003198 }
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303199 if (status == 0) {
3200 if (adev->speaker_lr_swap != reverse_speakers) {
3201 adev->speaker_lr_swap = reverse_speakers;
3202 // only update the selected device if there is active pcm playback
3203 struct audio_usecase *usecase;
3204 struct listnode *node;
3205 list_for_each(node, &adev->usecase_list) {
3206 usecase = node_to_item(node, struct audio_usecase, list);
3207 if (usecase->type == PCM_PLAYBACK) {
Steve Kondik3abbbc82014-11-29 14:14:43 -08003208 status = select_devices(adev, usecase->id);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303209 break;
3210 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003211 }
3212 }
3213 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003214 }
3215
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003216 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003217
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003218done:
3219 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003220 pthread_mutex_unlock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303221 ALOGV("%s: exit with code(%d)", __func__, status);
3222 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003223}
3224
3225static char* adev_get_parameters(const struct audio_hw_device *dev,
3226 const char *keys)
3227{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003228 struct audio_device *adev = (struct audio_device *)dev;
3229 struct str_parms *reply = str_parms_create();
3230 struct str_parms *query = str_parms_create_str(keys);
3231 char *str;
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303232 char value[256] = {0};
3233 int ret = 0;
3234
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003235 if (!query || !reply) {
3236 ALOGE("adev_get_parameters: failed to create query or reply");
3237 return NULL;
3238 }
3239
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303240 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
3241 sizeof(value));
3242 if (ret >=0) {
3243 int val = 1;
3244 pthread_mutex_lock(&adev->snd_card_status.lock);
3245 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3246 val = 0;
3247 pthread_mutex_unlock(&adev->snd_card_status.lock);
3248 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, val);
3249 goto exit;
3250 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003251
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003252 pthread_mutex_lock(&adev->lock);
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303253
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003254 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003255 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003256 platform_get_parameters(adev->platform, query, reply);
Naresh Tannirucef332d2014-06-04 18:17:56 +05303257 pthread_mutex_unlock(&adev->lock);
3258
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303259exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003260 str = str_parms_to_str(reply);
3261 str_parms_destroy(query);
3262 str_parms_destroy(reply);
3263
3264 ALOGV("%s: exit: returns - %s", __func__, str);
3265 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003266}
3267
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303268static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269{
3270 return 0;
3271}
3272
3273static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3274{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003275 int ret;
3276 struct audio_device *adev = (struct audio_device *)dev;
Eric Laurent321b96d2014-09-10 13:21:01 -05003277
3278 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3279
Haynes Mathew George5191a852013-09-11 14:19:36 -07003280 pthread_mutex_lock(&adev->lock);
3281 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003282 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003283 pthread_mutex_unlock(&adev->lock);
3284 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285}
3286
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303287static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3288 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003289{
3290 return -ENOSYS;
3291}
3292
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303293static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3294 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295{
3296 return -ENOSYS;
3297}
3298
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303299static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3300 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301{
3302 return -ENOSYS;
3303}
3304
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303305static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3306 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307{
3308 return -ENOSYS;
3309}
3310
3311static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3312{
3313 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003314 pthread_mutex_lock(&adev->lock);
3315 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003316 ALOGD("%s mode %d\n", __func__, mode);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303317 if (amplifier_set_mode(mode) != 0)
3318 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003319 adev->mode = mode;
3320 }
3321 pthread_mutex_unlock(&adev->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003322
3323 audio_extn_extspk_set_mode(adev->extspk, mode);
3324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325 return 0;
3326}
3327
3328static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3329{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003330 int ret;
3331
3332 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003333 ALOGD("%s state %d\n", __func__, state);
Shreyas Nagasandra Chandrasekhar9781c6c2014-12-01 05:49:35 -08003334 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003335 pthread_mutex_unlock(&adev->lock);
3336
3337 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338}
3339
3340static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3341{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003342 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 return 0;
3344}
3345
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303346static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347 const struct audio_config *config)
3348{
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303349 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003351 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3352 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353}
3354
3355static int adev_open_input_stream(struct audio_hw_device *dev,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303356 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357 audio_devices_t devices,
3358 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303359 struct audio_stream_in **stream_in,
3360 audio_input_flags_t flags __unused,
3361 const char *address __unused,
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003362 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363{
3364 struct audio_device *adev = (struct audio_device *)dev;
3365 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003366 int ret = 0, buffer_size, frame_size;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303367 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003368 bool is_low_latency = false;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 *stream_in = NULL;
3371 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3372 return -EINVAL;
3373
3374 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003375
3376 if (!in) {
3377 ALOGE("failed to allocate input stream");
3378 return -ENOMEM;
3379 }
3380
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303381 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003382 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3383 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003385 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 in->stream.common.get_sample_rate = in_get_sample_rate;
3388 in->stream.common.set_sample_rate = in_set_sample_rate;
3389 in->stream.common.get_buffer_size = in_get_buffer_size;
3390 in->stream.common.get_channels = in_get_channels;
3391 in->stream.common.get_format = in_get_format;
3392 in->stream.common.set_format = in_set_format;
3393 in->stream.common.standby = in_standby;
3394 in->stream.common.dump = in_dump;
3395 in->stream.common.set_parameters = in_set_parameters;
3396 in->stream.common.get_parameters = in_get_parameters;
3397 in->stream.common.add_audio_effect = in_add_audio_effect;
3398 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3399 in->stream.set_gain = in_set_gain;
3400 in->stream.read = in_read;
3401 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3402
3403 in->device = devices;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003404 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003406 in->standby = 1;
3407 in->channel_mask = config->channel_mask;
3408
3409 /* Update config params with the requested sample rate and channels */
3410 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003411 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3412 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3413 is_low_latency = true;
3414#if LOW_LATENCY_CAPTURE_USE_CASE
3415 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3416#endif
3417 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003418 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003419 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003420 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003421
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303422 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkala3c0036d2014-12-17 16:45:10 +05303423 if (adev->mode != AUDIO_MODE_IN_CALL) {
3424 ret = -EINVAL;
3425 goto err_open;
Pavan Chikkala3ec42ef2014-11-21 20:57:48 +05303426 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303427 if (config->sample_rate == 0)
3428 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3429 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3430 config->sample_rate != 8000) {
3431 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3432 ret = -EINVAL;
3433 goto err_open;
3434 }
3435 if (config->format == AUDIO_FORMAT_DEFAULT)
3436 config->format = AUDIO_FORMAT_PCM_16_BIT;
3437 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3438 config->format = AUDIO_FORMAT_PCM_16_BIT;
3439 ret = -EINVAL;
3440 goto err_open;
3441 }
3442 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3443 in->config = pcm_config_afe_proxy_record;
3444 in->config.channels = channel_count;
3445 in->config.rate = config->sample_rate;
3446 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003447 if(audio_extn_ssr_get_enabled()) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303448 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003449 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3450 ret = -EINVAL;
3451 goto err_open;
3452 }
3453 } else {
Mingming Yindaf9c542014-09-16 17:41:33 -07003454 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003455 }
Mingming Yine62d7842013-10-25 16:26:03 -07003456 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08003457 audio_extn_compr_cap_format_supported(config->format) &&
3458 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303459 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003460 } else {
3461 in->config.channels = channel_count;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303462 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003463 buffer_size = get_input_buffer_size(config->sample_rate,
3464 config->format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003465 channel_count,
3466 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003467 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003468 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3469 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3470 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3471 (in->config.rate == 8000 || in->config.rate == 16000) &&
3472 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3473 voice_extn_compress_voip_open_input_stream(in);
3474 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003475 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003476
3477 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003478 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003479 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003480
3481err_open:
3482 free(in);
3483 *stream_in = NULL;
3484 return ret;
3485}
3486
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303487static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003488 struct audio_stream_in *stream)
3489{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003490 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003491 struct stream_in *in = (struct stream_in *)stream;
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303492 struct audio_device *adev = in->dev;
3493
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303494 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003495
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003496 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303497 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003498 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303499 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003500 if (ret != 0)
3501 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3502 __func__, ret);
3503 } else
3504 in_standby(&stream->common);
3505
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303506 if (audio_extn_ssr_get_enabled() &&
3507 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003508 audio_extn_ssr_deinit();
3509 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510 free(stream);
3511
Mingming Yine62d7842013-10-25 16:26:03 -07003512 if(audio_extn_compr_cap_enabled() &&
3513 audio_extn_compr_cap_format_supported(in->config.format))
3514 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003515 return;
3516}
3517
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303518static int adev_dump(const audio_hw_device_t *device __unused,
3519 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003520{
3521 return 0;
3522}
3523
Steve Kondik3abbbc82014-11-29 14:14:43 -08003524/* verifies input and output devices and their capabilities.
3525 *
3526 * This verification is required when enabling extended bit-depth or
3527 * sampling rates, as not all qcom products support it.
3528 *
3529 * Suitable for calling only on initialization such as adev_open().
3530 * It fills the audio_device use_case_table[] array.
3531 *
3532 * Has a side-effect that it needs to configure audio routing / devices
3533 * in order to power up the devices and read the device parameters.
3534 * It does not acquire any hw device lock. Should restore the devices
3535 * back to "normal state" upon completion.
3536 */
3537static int adev_verify_devices(struct audio_device *adev)
3538{
3539 /* enumeration is a bit difficult because one really wants to pull
3540 * the use_case, device id, etc from the hidden pcm_device_table[].
3541 * In this case there are the following use cases and device ids.
3542 *
3543 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3544 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3545 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3546 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3547 * [USECASE_AUDIO_RECORD] = {0, 0},
3548 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3549 * [USECASE_VOICE_CALL] = {2, 2},
3550 *
3551 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3552 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3553 */
3554
3555 /* should be the usecases enabled in adev_open_input_stream() */
3556 static const int test_in_usecases[] = {
3557 USECASE_AUDIO_RECORD,
3558 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3559 };
3560 /* should be the usecases enabled in adev_open_output_stream()*/
3561 static const int test_out_usecases[] = {
3562 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3563 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3564 };
3565 static const usecase_type_t usecase_type_by_dir[] = {
3566 PCM_PLAYBACK,
3567 PCM_CAPTURE,
3568 };
3569 static const unsigned flags_by_dir[] = {
3570 PCM_OUT,
3571 PCM_IN,
3572 };
3573
3574 size_t i;
3575 unsigned dir;
3576 const unsigned card_id = adev->snd_card;
3577 char info[512]; /* for possible debug info */
3578
3579 for (dir = 0; dir < 2; ++dir) {
3580 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3581 const unsigned flags_dir = flags_by_dir[dir];
3582 const size_t testsize =
3583 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3584 const int *testcases =
3585 dir ? test_in_usecases : test_out_usecases;
3586 const audio_devices_t audio_device =
3587 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3588
3589 for (i = 0; i < testsize; ++i) {
3590 const audio_usecase_t audio_usecase = testcases[i];
3591 int device_id;
3592 snd_device_t snd_device;
3593 struct pcm_params **pparams;
3594 struct stream_out out;
3595 struct stream_in in;
3596 struct audio_usecase uc_info;
3597 int retval;
3598
3599 pparams = &adev->use_case_table[audio_usecase];
3600 pcm_params_free(*pparams); /* can accept null input */
3601 *pparams = NULL;
3602
3603 /* find the device ID for the use case (signed, for error) */
3604 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3605 if (device_id < 0)
3606 continue;
3607
3608 /* prepare structures for device probing */
3609 memset(&uc_info, 0, sizeof(uc_info));
3610 uc_info.id = audio_usecase;
3611 uc_info.type = usecase_type;
3612 if (dir) {
3613 adev->active_input = &in;
3614 memset(&in, 0, sizeof(in));
3615 in.device = audio_device;
3616 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3617 uc_info.stream.in = &in;
3618 } else {
3619 adev->active_input = NULL;
3620 }
3621 memset(&out, 0, sizeof(out));
3622 out.devices = audio_device; /* only field needed in select_devices */
3623 uc_info.stream.out = &out;
3624 uc_info.devices = audio_device;
3625 uc_info.in_snd_device = SND_DEVICE_NONE;
3626 uc_info.out_snd_device = SND_DEVICE_NONE;
3627 list_add_tail(&adev->usecase_list, &uc_info.list);
3628
3629 /* select device - similar to start_(in/out)put_stream() */
3630 retval = select_devices(adev, audio_usecase);
3631 if (retval >= 0) {
3632 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3633#if LOG_NDEBUG == 0
3634 if (*pparams) {
3635 ALOGV("%s: (%s) card %d device %d", __func__,
3636 dir ? "input" : "output", card_id, device_id);
3637 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
3638 ALOGV(info); /* print parameters */
3639 } else {
3640 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3641 }
3642#endif
3643 }
3644
3645 /* deselect device - similar to stop_(in/out)put_stream() */
3646 /* 1. Get and set stream specific mixer controls */
3647 retval = disable_audio_route(adev, &uc_info);
3648 /* 2. Disable the rx device */
3649 retval = disable_snd_device(adev,
3650 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
3651 list_remove(&uc_info.list);
3652 }
3653 }
3654 adev->active_input = NULL; /* restore adev state */
3655 return 0;
3656}
3657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003658static int adev_close(hw_device_t *device)
3659{
Steve Kondik3abbbc82014-11-29 14:14:43 -08003660 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003661 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003662
3663 if (!adev)
3664 return 0;
3665
3666 pthread_mutex_lock(&adev_init_lock);
3667
3668 if ((--audio_device_ref_count) == 0) {
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303669 if (amplifier_close() != 0)
3670 ALOGE("Amplifier close failed");
Kiran Kandide144c82013-11-20 15:58:32 -08003671 audio_extn_listen_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07003672 audio_route_free(adev->audio_route);
3673 free(adev->snd_dev_ref_cnt);
3674 platform_deinit(adev->platform);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003675 audio_extn_extspk_deinit(adev->extspk);
Steve Kondik3abbbc82014-11-29 14:14:43 -08003676 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3677 pcm_params_free(adev->use_case_table[i]);
3678 }
Kiran Kandi910e1862013-10-29 13:29:42 -07003679 free(device);
3680 adev = NULL;
3681 }
3682 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003683 return 0;
3684}
3685
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003686/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3687 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3688 * just that it _might_ work.
3689 */
3690static int period_size_is_plausible_for_low_latency(int period_size)
3691{
3692 switch (period_size) {
3693 case 160:
3694 case 240:
3695 case 320:
3696 case 480:
3697 return 1;
3698 default:
3699 return 0;
3700 }
3701}
3702
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003703static int adev_open(const hw_module_t *module, const char *name,
3704 hw_device_t **device)
3705{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003706 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003707
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003708 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3710
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003711 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003712 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003713 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003714 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003715 ALOGD("%s: returning existing instance of adev", __func__);
3716 ALOGD("%s: exit", __func__);
3717 pthread_mutex_unlock(&adev_init_lock);
3718 return 0;
3719 }
3720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003721 adev = calloc(1, sizeof(struct audio_device));
3722
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003723 if (!adev) {
3724 pthread_mutex_unlock(&adev_init_lock);
3725 return -ENOMEM;
3726 }
3727
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003728 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3731 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3732 adev->device.common.module = (struct hw_module_t *)module;
3733 adev->device.common.close = adev_close;
3734
3735 adev->device.init_check = adev_init_check;
3736 adev->device.set_voice_volume = adev_set_voice_volume;
3737 adev->device.set_master_volume = adev_set_master_volume;
3738 adev->device.get_master_volume = adev_get_master_volume;
3739 adev->device.set_master_mute = adev_set_master_mute;
3740 adev->device.get_master_mute = adev_get_master_mute;
3741 adev->device.set_mode = adev_set_mode;
3742 adev->device.set_mic_mute = adev_set_mic_mute;
3743 adev->device.get_mic_mute = adev_get_mic_mute;
3744 adev->device.set_parameters = adev_set_parameters;
3745 adev->device.get_parameters = adev_get_parameters;
3746 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3747 adev->device.open_output_stream = adev_open_output_stream;
3748 adev->device.close_output_stream = adev_close_output_stream;
3749 adev->device.open_input_stream = adev_open_input_stream;
3750 adev->device.close_input_stream = adev_close_input_stream;
3751 adev->device.dump = adev_dump;
3752
3753 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003755 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003756 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003759 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003760 /* adev->cur_hdmi_channels = 0; by calloc() */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08003761 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3762 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003763 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003764 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003765 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly9b7e96b2014-02-14 14:45:49 -08003766 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003767 adev->offload_usecases_state = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303769 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3770 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
3771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003773 adev->platform = platform_init(adev);
3774 if (!adev->platform) {
3775 free(adev->snd_dev_ref_cnt);
3776 free(adev);
3777 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3778 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003779 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003780 return -EINVAL;
3781 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003782
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303783 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
Eric Laurentda46bfb2014-08-25 22:39:29 -05003784 adev->extspk = audio_extn_extspk_init(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303785
Eric Laurentc4aef752013-09-12 17:45:53 -07003786 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3787 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3788 if (adev->visualizer_lib == NULL) {
3789 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3790 } else {
3791 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3792 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003793 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003794 "visualizer_hal_start_output");
3795 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003796 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003797 "visualizer_hal_stop_output");
3798 }
3799 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003800 audio_extn_listen_init(adev, adev->snd_card);
Eric Laurentc4aef752013-09-12 17:45:53 -07003801
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003802 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3803 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3804 if (adev->offload_effects_lib == NULL) {
3805 ALOGE("%s: DLOPEN failed for %s", __func__,
3806 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3807 } else {
3808 ALOGV("%s: DLOPEN successful for %s", __func__,
3809 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3810 adev->offload_effects_start_output =
3811 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3812 "offload_effects_bundle_hal_start_output");
3813 adev->offload_effects_stop_output =
3814 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3815 "offload_effects_bundle_hal_stop_output");
3816 }
3817 }
3818
Dan Pasanend4c2ca92015-08-10 19:47:43 -05003819 if (amplifier_open() != 0)
3820 ALOGE("Amplifier initialization failed");
3821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003822 *device = &adev->device.common;
Steve Kondik3abbbc82014-11-29 14:14:43 -08003823 if (k_enable_extended_precision)
3824 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003825
Kiran Kandi910e1862013-10-29 13:29:42 -07003826 audio_device_ref_count++;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003827
3828 char value[PROPERTY_VALUE_MAX];
3829 int trial;
3830 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3831 trial = atoi(value);
3832 if (period_size_is_plausible_for_low_latency(trial)) {
3833 pcm_config_low_latency.period_size = trial;
3834 pcm_config_low_latency.start_threshold = trial / 4;
3835 pcm_config_low_latency.avail_min = trial / 4;
3836 configured_low_latency_capture_period_size = trial;
3837 }
3838 }
3839 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3840 trial = atoi(value);
3841 if (period_size_is_plausible_for_low_latency(trial)) {
3842 configured_low_latency_capture_period_size = trial;
3843 }
3844 }
3845
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003846 pthread_mutex_unlock(&adev_init_lock);
3847
Eric Laurent994a6932013-07-17 11:51:42 -07003848 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003849 return 0;
3850}
3851
3852static struct hw_module_methods_t hal_module_methods = {
3853 .open = adev_open,
3854};
3855
3856struct audio_module HAL_MODULE_INFO_SYM = {
3857 .common = {
3858 .tag = HARDWARE_MODULE_TAG,
3859 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3860 .hal_api_version = HARDWARE_HAL_API_VERSION,
3861 .id = AUDIO_HARDWARE_MODULE_ID,
3862 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003863 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003864 .methods = &hal_module_methods,
3865 },
3866};