blob: f3223076e260dddbbf1c5cb60309d33d4aea5225 [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{
233 int rc;
234 amplifier_module_t *module;
235
236 if (adev->amp)
237 return adev->amp;
238
239 rc = hw_get_module(AMPLIFIER_HARDWARE_MODULE_ID,
240 (const hw_module_t **) &module);
241 if (rc) {
242 ALOGV("%s: Failed to obtain reference to amplifier module: %s\n",
243 __func__, strerror(-rc));
244 return NULL;
245 }
246
247 rc = amplifier_device_open((const hw_module_t *) module, &adev->amp);
248 if (rc) {
249 ALOGV("%s: Failed to open amplifier hardware device: %s\n",
250 __func__, strerror(-rc));
251 return NULL;
252 }
253
254 return adev->amp;
255}
256
257static int amplifier_open(void)
258{
259 amplifier_device_t *amp = get_amplifier_device();
260
261 if (!amp) {
262 return -ENODEV;
263 }
264
265 return 0;
266}
267
268static int amplifier_set_input_devices(uint32_t devices)
269{
270 amplifier_device_t *amp = get_amplifier_device();
271 if (amp && amp->set_input_devices)
272 return amp->set_input_devices(amp, devices);
273
274 return 0;
275}
276
277static int amplifier_set_output_devices(uint32_t devices)
278{
279 amplifier_device_t *amp = get_amplifier_device();
280 if (amp && amp->set_output_devices)
281 return amp->set_output_devices(amp, devices);
282
283 return 0;
284}
285
286static int amplifier_set_mode(audio_mode_t mode)
287{
288 amplifier_device_t *amp = get_amplifier_device();
289 if (amp && amp->set_mode)
290 return amp->set_mode(amp, mode);
291
292 return 0;
293}
294
295static int amplifier_output_stream_start(struct audio_stream_out *stream,
296 bool offload)
297{
298 amplifier_device_t *amp = get_amplifier_device();
299 if (amp && amp->output_stream_start)
300 return amp->output_stream_start(amp, stream, offload);
301
302 return 0;
303}
304
305static int amplifier_input_stream_start(struct audio_stream_in *stream)
306{
307 amplifier_device_t *amp = get_amplifier_device();
308 if (amp && amp->input_stream_start)
309 return amp->input_stream_start(amp, stream);
310
311 return 0;
312}
313
314static int amplifier_output_stream_standby(struct audio_stream_out *stream)
315{
316 amplifier_device_t *amp = get_amplifier_device();
317 if (amp && amp->output_stream_standby)
318 return amp->output_stream_standby(amp, stream);
319
320 return 0;
321}
322
323static int amplifier_input_stream_standby(struct audio_stream_in *stream)
324{
325 amplifier_device_t *amp = get_amplifier_device();
326 if (amp && amp->input_stream_standby)
327 return amp->input_stream_standby(amp, stream);
328
329 return 0;
330}
331
332static int amplifier_close(void)
333{
334 amplifier_device_t *amp = get_amplifier_device();
335 if (amp)
336 amplifier_device_close(amp);
337
338 return 0;
339}
340
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800341static int check_and_set_gapless_mode(struct audio_device *adev) {
342
343
344 char value[PROPERTY_VALUE_MAX] = {0};
345 bool gapless_enabled = false;
346 const char *mixer_ctl_name = "Compress Gapless Playback";
347 struct mixer_ctl *ctl;
348
349 ALOGV("%s:", __func__);
350 property_get("audio.offload.gapless.enabled", value, NULL);
351 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
352
353 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
354 if (!ctl) {
355 ALOGE("%s: Could not get ctl for mixer cmd - %s",
356 __func__, mixer_ctl_name);
357 return -EINVAL;
358 }
359
360 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
361 ALOGE("%s: Could not set gapless mode %d",
362 __func__, gapless_enabled);
363 return -EINVAL;
364 }
365 return 0;
366}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700367
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700368static bool is_supported_format(audio_format_t format)
369{
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800370 switch (format) {
Steve Kondik3abbbc82014-11-29 14:14:43 -0800371 case AUDIO_FORMAT_MP3:
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800372 case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
373 case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700374#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik3abbbc82014-11-29 14:14:43 -0800375 case AUDIO_FORMAT_FLAC:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700376#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -0800377#ifdef WMA_OFFLOAD_ENABLED
378 case AUDIO_FORMAT_WMA:
379 case AUDIO_FORMAT_WMA_PRO:
380#endif
381#ifdef MP2_OFFLOAD_ENABLED
382 case AUDIO_FORMAT_MP2:
383#endif
384 case AUDIO_FORMAT_AAC_LC:
385 case AUDIO_FORMAT_AAC_HE_V1:
386 case AUDIO_FORMAT_AAC_HE_V2:
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530387 return true;
Steve Kondik3abbbc82014-11-29 14:14:43 -0800388
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800389 default:
390 return false;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530391 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700392 return false;
393}
394
395static int get_snd_codec_id(audio_format_t format)
396{
397 int id = 0;
398
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530399 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700400 case AUDIO_FORMAT_MP3:
401 id = SND_AUDIOCODEC_MP3;
402 break;
403 case AUDIO_FORMAT_AAC:
404 id = SND_AUDIOCODEC_AAC;
405 break;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530406 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapu0c566872014-01-10 14:46:02 -0800407 id = SND_AUDIOCODEC_PCM;
408 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700409#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800410 case AUDIO_FORMAT_FLAC:
411 id = SND_AUDIOCODEC_FLAC;
412 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700413#endif
Ethan Chenc856d972014-07-25 14:57:15 -0700414#ifdef WMA_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700415 case AUDIO_FORMAT_WMA:
416 id = SND_AUDIOCODEC_WMA;
417 break;
418 case AUDIO_FORMAT_WMA_PRO:
419 id = SND_AUDIOCODEC_WMA_PRO;
420 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700421#endif
422#ifdef MP2_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700423 case AUDIO_FORMAT_MP2:
424 id = SND_AUDIOCODEC_MP2;
425 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700426#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700427 default:
Mingming Yin90310102013-11-13 16:57:00 -0800428 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700429 }
430
431 return id;
432}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800433
Avinash Vaish8005dc82014-07-24 15:36:33 +0530434static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
435 struct audio_usecase *uc_info)
436{
437 struct listnode *node;
438 struct audio_usecase *usecase;
439
440 if (uc_info == NULL)
441 return -EINVAL;
442
443 /* Re-route all voice usecases on the shared backend other than the
444 specified usecase to new snd devices */
445 list_for_each(node, &adev->usecase_list) {
446 usecase = node_to_item(node, struct audio_usecase, list);
447 if ((usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) &&
448 (usecase != uc_info))
449 enable_audio_route(adev, usecase);
450 }
451 return 0;
452}
453
Venkata Narendra Kumar Guttac9e9e2c2014-07-09 16:29:28 +0530454int get_snd_card_state(struct audio_device *adev)
Naresh Tannirucef332d2014-06-04 18:17:56 +0530455{
456 int snd_scard_state;
457
458 if (!adev)
459 return SND_CARD_STATE_OFFLINE;
460
461 pthread_mutex_lock(&adev->snd_card_status.lock);
462 snd_scard_state = adev->snd_card_status.state;
463 pthread_mutex_unlock(&adev->snd_card_status.lock);
464
465 return snd_scard_state;
466}
467
468static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
469{
470 if (!adev)
471 return -ENOSYS;
472
473 pthread_mutex_lock(&adev->snd_card_status.lock);
474 adev->snd_card_status.state = snd_scard_state;
475 pthread_mutex_unlock(&adev->snd_card_status.lock);
476
477 return 0;
478}
479
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -0700480int pcm_ioctl(struct pcm *pcm, int request, ...)
481{
482 va_list ap;
483 void * arg;
484 int pcm_fd = *(int*)pcm;
485
486 va_start(ap, request);
487 arg = va_arg(ap, void *);
488 va_end(ap);
489
490 return ioctl(pcm_fd, request, arg);
491}
492
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700493int enable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700494 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800495{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700496 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700497 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800498
499 if (usecase == NULL)
500 return -EINVAL;
501
502 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
503
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800504 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800506 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700507 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800508
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -0800509#ifdef DS1_DOLBY_DAP_ENABLED
510 audio_extn_dolby_set_dmid(adev);
511 audio_extn_dolby_set_endpoint(adev);
512#endif
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800513 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700514 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700515 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
516 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800517 ALOGV("%s: exit", __func__);
518 return 0;
519}
520
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700521int disable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700522 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800523{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700524 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700525 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800526
527 if (usecase == NULL)
528 return -EINVAL;
529
530 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700531 if (usecase->type == PCM_CAPTURE)
532 snd_device = usecase->in_snd_device;
533 else
534 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800535 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700536 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700537 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
538 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800539 ALOGV("%s: exit", __func__);
540 return 0;
541}
542
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700543int enable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700544 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800545{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700546 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
547
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800548 if (snd_device < SND_DEVICE_MIN ||
549 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800550 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800551 return -EINVAL;
552 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700553
554 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700555
556 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
557 ALOGE("%s: Invalid sound device returned", __func__);
558 return -EINVAL;
559 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700560 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700561 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700562 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700563 return 0;
564 }
565
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700566 /* start usb playback thread */
567 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
568 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
569 audio_extn_usb_start_playback(adev);
570
571 /* start usb capture thread */
572 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
573 audio_extn_usb_start_capture(adev);
574
Tony Layher692f19a2015-01-03 13:16:45 -0500575 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
576 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700577 audio_extn_spkr_prot_is_enabled()) {
578 if (audio_extn_spkr_prot_start_processing(snd_device)) {
579 ALOGE("%s: spkr_start_processing failed", __func__);
580 return -EINVAL;
581 }
582 } else {
583 ALOGV("%s: snd_device(%d: %s)", __func__,
Steve Kondik6288f9e2014-12-27 13:36:30 -0800584 snd_device, device_name);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700585 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
586 adev->snd_dev_ref_cnt[snd_device]--;
587 return -EINVAL;
588 }
Steve Kondik6288f9e2014-12-27 13:36:30 -0800589 audio_extn_listen_update_status(snd_device,
590 LISTEN_EVENT_SND_DEVICE_BUSY);
Kiran Kandide144c82013-11-20 15:58:32 -0800591
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700592 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800593 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800594 return 0;
595}
596
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700597int disable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700598 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800599{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700600 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
601
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800602 if (snd_device < SND_DEVICE_MIN ||
603 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800604 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800605 return -EINVAL;
606 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700607 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
608 ALOGE("%s: device ref cnt is already 0", __func__);
609 return -EINVAL;
610 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700611
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700612 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700613
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700614 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
615 ALOGE("%s: Invalid sound device returned", __func__);
616 return -EINVAL;
617 }
618
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700619 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700620 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700621 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800622 /* exit usb play back thread */
623 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
624 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
625 audio_extn_usb_stop_playback();
626
627 /* exit usb capture thread */
628 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Rajshekar Eashwarappa4dfa0752014-10-02 20:18:20 +0530629 audio_extn_usb_stop_capture();
Tony Layher692f19a2015-01-03 13:16:45 -0500630
631 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
632 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700633 audio_extn_spkr_prot_is_enabled()) {
634 audio_extn_spkr_prot_stop_processing();
635 } else
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700636 audio_route_reset_and_update_path(adev->audio_route, device_name);
Kiran Kandide144c82013-11-20 15:58:32 -0800637
Steve Kondik6288f9e2014-12-27 13:36:30 -0800638 audio_extn_listen_update_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800639 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700640 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800642 return 0;
643}
644
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700645static void check_usecases_codec_backend(struct audio_device *adev,
646 struct audio_usecase *uc_info,
647 snd_device_t snd_device)
648{
649 struct listnode *node;
650 struct audio_usecase *usecase;
651 bool switch_device[AUDIO_USECASE_MAX];
652 int i, num_uc_to_switch = 0;
653
654 /*
655 * This function is to make sure that all the usecases that are active on
656 * the hardware codec backend are always routed to any one device that is
657 * handled by the hardware codec.
658 * For example, if low-latency and deep-buffer usecases are currently active
659 * on speaker and out_set_parameters(headset) is received on low-latency
660 * output, then we have to make sure deep-buffer is also switched to headset,
661 * because of the limitation that both the devices cannot be enabled
662 * at the same time as they share the same backend.
663 */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800664 /*
665 * This call is to check if we need to force routing for a particular stream
666 * If there is a backend configuration change for the device when a
667 * new stream starts, then ADM needs to be closed and re-opened with the new
668 * configuraion. This call check if we need to re-route all the streams
669 * associated with the backend. Touch tone + 24 bit playback.
670 */
671 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
672
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700673 /* Disable all the usecases on the shared backend other than the
674 specified usecase */
675 for (i = 0; i < AUDIO_USECASE_MAX; i++)
676 switch_device[i] = false;
677
678 list_for_each(node, &adev->usecase_list) {
679 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800680 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700681 usecase != uc_info &&
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800682 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700683 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
684 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
685 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700686 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700687 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700688 switch_device[usecase->id] = true;
689 num_uc_to_switch++;
690 }
691 }
692
693 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700694 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700695
696 list_for_each(node, &adev->usecase_list) {
697 usecase = node_to_item(node, struct audio_usecase, list);
698 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700699 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700700 }
701 }
702
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700703 list_for_each(node, &adev->usecase_list) {
704 usecase = node_to_item(node, struct audio_usecase, list);
705 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700706 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700707 }
708 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700709
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700710 /* Re-route all the usecases on the shared backend other than the
711 specified usecase to new snd devices */
712 list_for_each(node, &adev->usecase_list) {
713 usecase = node_to_item(node, struct audio_usecase, list);
714 /* Update the out_snd_device only before enabling the audio route */
715 if (switch_device[usecase->id] ) {
716 usecase->out_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530717 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
718 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700719 }
720 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700721 }
722}
723
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700724static void check_and_route_capture_usecases(struct audio_device *adev,
725 struct audio_usecase *uc_info,
726 snd_device_t snd_device)
727{
728 struct listnode *node;
729 struct audio_usecase *usecase;
730 bool switch_device[AUDIO_USECASE_MAX];
731 int i, num_uc_to_switch = 0;
732
733 /*
734 * This function is to make sure that all the active capture usecases
735 * are always routed to the same input sound device.
736 * For example, if audio-record and voice-call usecases are currently
737 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
738 * is received for voice call then we have to make sure that audio-record
739 * usecase is also switched to earpiece i.e. voice-dmic-ef,
740 * because of the limitation that two devices cannot be enabled
741 * at the same time if they share the same backend.
742 */
743 for (i = 0; i < AUDIO_USECASE_MAX; i++)
744 switch_device[i] = false;
745
746 list_for_each(node, &adev->usecase_list) {
747 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800748 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700749 usecase != uc_info &&
Avinash Vaish44014792015-03-27 14:46:04 +0530750 usecase->in_snd_device != snd_device &&
751 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700752 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
753 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700754 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700755 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700756 switch_device[usecase->id] = true;
757 num_uc_to_switch++;
758 }
759 }
760
761 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700762 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700763
764 list_for_each(node, &adev->usecase_list) {
765 usecase = node_to_item(node, struct audio_usecase, list);
766 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700767 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800768 }
769 }
770
771 list_for_each(node, &adev->usecase_list) {
772 usecase = node_to_item(node, struct audio_usecase, list);
773 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700774 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700775 }
776 }
777
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700778 /* Re-route all the usecases on the shared backend other than the
779 specified usecase to new snd devices */
780 list_for_each(node, &adev->usecase_list) {
781 usecase = node_to_item(node, struct audio_usecase, list);
782 /* Update the in_snd_device only before enabling the audio route */
783 if (switch_device[usecase->id] ) {
784 usecase->in_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530785 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
786 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700787 }
788 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700789 }
790}
791
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800792/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700793static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800794{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700795 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700796 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800797
798 switch (channels) {
799 /*
800 * Do not handle stereo output in Multi-channel cases
801 * Stereo case is handled in normal playback path
802 */
803 case 6:
804 ALOGV("%s: HDMI supports 5.1", __func__);
805 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
806 break;
807 case 8:
808 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
809 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
810 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
811 break;
812 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700813 ALOGE("HDMI does not support multi channel playback");
814 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800815 break;
816 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700817 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800818}
819
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700820static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
821{
822 struct audio_usecase *usecase;
823 struct listnode *node;
824
825 list_for_each(node, &adev->usecase_list) {
826 usecase = node_to_item(node, struct audio_usecase, list);
827 if (usecase->type == VOICE_CALL) {
828 ALOGV("%s: usecase id %d", __func__, usecase->id);
829 return usecase->id;
830 }
831 }
832 return USECASE_INVALID;
833}
834
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700835struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700836 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700837{
838 struct audio_usecase *usecase;
839 struct listnode *node;
840
841 list_for_each(node, &adev->usecase_list) {
842 usecase = node_to_item(node, struct audio_usecase, list);
843 if (usecase->id == uc_id)
844 return usecase;
845 }
846 return NULL;
847}
848
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700849int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800850{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800851 snd_device_t out_snd_device = SND_DEVICE_NONE;
852 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700853 struct audio_usecase *usecase = NULL;
854 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800855 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800856 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800857 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800858 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700859 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800860
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700861 usecase = get_usecase_from_list(adev, uc_id);
862 if (usecase == NULL) {
863 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
864 return -EINVAL;
865 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800866
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800867 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800868 (usecase->type == VOIP_CALL) ||
869 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700870 out_snd_device = platform_get_output_snd_device(adev->platform,
871 usecase->stream.out->devices);
872 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 usecase->devices = usecase->stream.out->devices;
874 } else {
875 /*
876 * If the voice call is active, use the sound devices of voice call usecase
877 * so that it would not result any device switch. All the usecases will
878 * be switched to new device when select_devices() is called for voice call
879 * usecase. This is to avoid switching devices for voice call when
880 * check_usecases_codec_backend() is called below.
881 */
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -0700882 if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700883 vc_usecase = get_usecase_from_list(adev,
884 get_voice_usecase_id_from_list(adev));
Mingming Yin6c23f382014-08-14 00:00:51 -0700885 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
886 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700887 in_snd_device = vc_usecase->in_snd_device;
888 out_snd_device = vc_usecase->out_snd_device;
889 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800890 } else if (voice_extn_compress_voip_is_active(adev)) {
891 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin6c23f382014-08-14 00:00:51 -0700892 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish6a4c3372014-06-25 12:20:37 +0530893 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin6c23f382014-08-14 00:00:51 -0700894 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800895 in_snd_device = voip_usecase->in_snd_device;
896 out_snd_device = voip_usecase->out_snd_device;
897 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800898 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800899 hfp_ucid = audio_extn_hfp_get_usecase();
900 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin6c23f382014-08-14 00:00:51 -0700901 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800902 in_snd_device = hfp_usecase->in_snd_device;
903 out_snd_device = hfp_usecase->out_snd_device;
904 }
Vimal Puthanveed8fa9eab2014-01-07 16:47:47 -0800905 } else if (audio_extn_hfp_is_active(adev)) {
906 hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
907 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
908 in_snd_device = hfp_usecase->in_snd_device;
909 out_snd_device = hfp_usecase->out_snd_device;
910 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700911 }
912 if (usecase->type == PCM_PLAYBACK) {
913 usecase->devices = usecase->stream.out->devices;
914 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700915 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700916 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700917 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700918 if (usecase->stream.out == adev->primary_output &&
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530919 adev->active_input ) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700920 select_devices(adev, adev->active_input->usecase);
921 }
922 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700923 } else if (usecase->type == PCM_CAPTURE) {
924 usecase->devices = usecase->stream.in->device;
925 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700926 if (in_snd_device == SND_DEVICE_NONE) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530927 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530928 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 -0700929 adev->primary_output && !adev->primary_output->standby) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530930 out_device = adev->primary_output->devices;
931 } else if(usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
932 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700933 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530934 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700935 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700936 }
937 }
938
939 if (out_snd_device == usecase->out_snd_device &&
940 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800941 return 0;
942 }
943
sangwoobc677242013-08-08 16:53:43 +0900944 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700945 out_snd_device, platform_get_snd_device_name(out_snd_device),
946 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800947
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800948 /*
949 * Limitation: While in call, to do a device switch we need to disable
950 * and enable both RX and TX devices though one of them is same as current
951 * device.
952 */
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800953 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700954 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800955 }
956
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700957 /* Disable current sound devices */
958 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700959 disable_audio_route(adev, usecase);
960 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800961 }
962
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700963 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700964 disable_audio_route(adev, usecase);
965 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 }
967
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700968 /* Enable new sound devices */
969 if (out_snd_device != SND_DEVICE_NONE) {
970 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
971 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700972 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800973 }
974
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700975 if (in_snd_device != SND_DEVICE_NONE) {
976 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700977 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700978 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979
Avinash Vaish8005dc82014-07-24 15:36:33 +0530980 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700981 status = platform_switch_voice_call_device_post(adev->platform,
982 out_snd_device,
983 in_snd_device);
Avinash Vaish8005dc82014-07-24 15:36:33 +0530984 enable_audio_route_for_voice_usecases(adev, usecase);
985 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800986
sangwoo170731f2013-06-08 15:36:36 +0900987 usecase->in_snd_device = in_snd_device;
988 usecase->out_snd_device = out_snd_device;
989
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700990 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +0900991
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +0530992 /* Rely on amplifier_set_devices to distinguish between in/out devices */
Ethan Chen79c356c2015-06-07 12:26:14 -0700993 amplifier_set_input_devices(in_snd_device);
994 amplifier_set_output_devices(out_snd_device);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +0530995
Vidyakumar Athota1fd21792013-11-15 14:50:57 -0800996 /* Applicable only on the targets that has external modem.
997 * Enable device command should be sent to modem only after
998 * enabling voice call mixer controls
999 */
1000 if (usecase->type == VOICE_CALL)
1001 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1002 out_snd_device,
1003 in_snd_device);
1004
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301005 ALOGD("%s: done",__func__);
1006
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007 return status;
1008}
1009
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001010static int stop_input_stream(struct stream_in *in)
1011{
1012 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001013 struct audio_usecase *uc_info;
1014 struct audio_device *adev = in->dev;
1015
Eric Laurentc8400632013-02-14 19:04:54 -08001016 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001017
Eric Laurent994a6932013-07-17 11:51:42 -07001018 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001019 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001020 uc_info = get_usecase_from_list(adev, in->usecase);
1021 if (uc_info == NULL) {
1022 ALOGE("%s: Could not find the usecase (%d) in the list",
1023 __func__, in->usecase);
1024 return -EINVAL;
1025 }
1026
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001027 /* Close in-call recording streams */
1028 voice_check_and_stop_incall_rec_usecase(adev, in);
1029
Eric Laurent150dbfe2013-02-27 14:31:02 -08001030 /* 1. Disable stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001031 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001032
1033 /* 2. Disable the tx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001034 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001036 list_remove(&uc_info->list);
1037 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038
Eric Laurent994a6932013-07-17 11:51:42 -07001039 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040 return ret;
1041}
1042
1043int start_input_stream(struct stream_in *in)
1044{
1045 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001046 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047 struct audio_usecase *uc_info;
1048 struct audio_device *adev = in->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301049 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001050
Ramjee Singh240ac652015-07-31 16:12:29 +05301051 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1052 if (get_usecase_from_list(adev, usecase) == NULL)
1053 in->usecase = usecase;
1054
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301055 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1056 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001057
Naresh Tannirucef332d2014-06-04 18:17:56 +05301058 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
1059 ALOGE("%s: sound card is not active/SSR returning error ", __func__);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301060 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301061 goto error_config;
1062 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301063
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001064 /* Check if source matches incall recording usecase criteria */
1065 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1066 if (ret)
1067 goto error_config;
1068 else
1069 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1070
Ramjee Singh240ac652015-07-31 16:12:29 +05301071 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1072 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1073 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1074 goto error_config;
1075 }
1076
Eric Laurentb23d5282013-05-14 15:27:20 -07001077 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001078 if (in->pcm_device_id < 0) {
1079 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1080 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001081 ret = -EINVAL;
1082 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001083 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001084
1085 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001086 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001087
1088 if (!uc_info) {
1089 ret = -ENOMEM;
1090 goto error_config;
1091 }
1092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001093 uc_info->id = in->usecase;
1094 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001095 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001096 uc_info->devices = in->device;
1097 uc_info->in_snd_device = SND_DEVICE_NONE;
1098 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001099
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001100 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001101 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001102
Eric Laurentc8400632013-02-14 19:04:54 -08001103 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301104 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1105
1106 unsigned int flags = PCM_IN;
1107 unsigned int pcm_open_retry_entry_count = 0;
1108
1109 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1110 flags |= PCM_MMAP | PCM_NOIRQ;
1111 pcm_open_retry_entry_count = PROXY_OPEN_RETRY_COUNT;
1112 }
1113
1114 while(1) {
1115 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1116 flags, &in->config);
1117 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1118 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1119 if (in->pcm != NULL) {
1120 pcm_close(in->pcm);
1121 in->pcm = NULL;
1122 }
1123 if (pcm_open_retry_entry_count-- == 0) {
1124 ret = -EIO;
1125 goto error_open;
1126 }
1127 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1128 continue;
1129 }
1130 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001131 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301132
Eric Laurent994a6932013-07-17 11:51:42 -07001133 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001134 return ret;
1135
1136error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001137 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001138
1139error_config:
1140 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001141 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001142
1143 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001144}
1145
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001146/* must be called with out->lock locked */
1147static int send_offload_cmd_l(struct stream_out* out, int command)
1148{
1149 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1150
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001151 if (!cmd) {
1152 ALOGE("failed to allocate mem for command 0x%x", command);
1153 return -ENOMEM;
1154 }
1155
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001156 ALOGVV("%s %d", __func__, command);
1157
1158 cmd->cmd = command;
1159 list_add_tail(&out->offload_cmd_list, &cmd->node);
1160 pthread_cond_signal(&out->offload_cond);
1161 return 0;
1162}
1163
1164/* must be called iwth out->lock locked */
1165static void stop_compressed_output_l(struct stream_out *out)
1166{
1167 out->offload_state = OFFLOAD_STATE_IDLE;
1168 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001169 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001170 if (out->compr != NULL) {
1171 compress_stop(out->compr);
1172 while (out->offload_thread_blocked) {
1173 pthread_cond_wait(&out->cond, &out->lock);
1174 }
1175 }
1176}
1177
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001178bool is_offload_usecase(audio_usecase_t uc_id)
1179{
1180 unsigned int i;
1181 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1182 if (uc_id == offload_usecases[i])
1183 return true;
1184 }
1185 return false;
1186}
1187
1188static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1189{
1190 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1191 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1192 char value[PROPERTY_VALUE_MAX] = {0};
1193
1194 property_get("audio.offload.multiple.enabled", value, NULL);
1195 if (!(atoi(value) || !strncmp("true", value, 4)))
1196 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1197
1198 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1199 for (i = 0; i < num_usecase; i++) {
1200 if (!(adev->offload_usecases_state & (0x1<<i))) {
1201 adev->offload_usecases_state |= 0x1 << i;
1202 ret = offload_usecases[i];
1203 break;
1204 }
1205 }
1206 ALOGV("%s: offload usecase is %d", __func__, ret);
1207 return ret;
1208}
1209
1210static void free_offload_usecase(struct audio_device *adev,
1211 audio_usecase_t uc_id)
1212{
1213 unsigned int i;
1214 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1215 if (offload_usecases[i] == uc_id) {
1216 adev->offload_usecases_state &= ~(0x1<<i);
1217 break;
1218 }
1219 }
1220 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1221}
1222
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001223static void *offload_thread_loop(void *context)
1224{
1225 struct stream_out *out = (struct stream_out *) context;
1226 struct listnode *item;
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001227 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001228
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001229 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1230 set_sched_policy(0, SP_FOREGROUND);
1231 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1232
1233 ALOGV("%s", __func__);
1234 pthread_mutex_lock(&out->lock);
1235 for (;;) {
1236 struct offload_cmd *cmd = NULL;
1237 stream_callback_event_t event;
1238 bool send_callback = false;
1239
1240 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1241 __func__, list_empty(&out->offload_cmd_list),
1242 out->offload_state);
1243 if (list_empty(&out->offload_cmd_list)) {
1244 ALOGV("%s SLEEPING", __func__);
1245 pthread_cond_wait(&out->offload_cond, &out->lock);
1246 ALOGV("%s RUNNING", __func__);
1247 continue;
1248 }
1249
1250 item = list_head(&out->offload_cmd_list);
1251 cmd = node_to_item(item, struct offload_cmd, node);
1252 list_remove(item);
1253
1254 ALOGVV("%s STATE %d CMD %d out->compr %p",
1255 __func__, out->offload_state, cmd->cmd, out->compr);
1256
1257 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1258 free(cmd);
1259 break;
1260 }
1261
1262 if (out->compr == NULL) {
1263 ALOGE("%s: Compress handle is NULL", __func__);
1264 pthread_cond_signal(&out->cond);
1265 continue;
1266 }
1267 out->offload_thread_blocked = true;
1268 pthread_mutex_unlock(&out->lock);
1269 send_callback = false;
1270 switch(cmd->cmd) {
1271 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Steve Kondik05c17962015-02-25 00:55:50 -08001272 ALOGV("copl(%x):calling compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001273 compress_wait(out->compr, -1);
Steve Kondik05c17962015-02-25 00:55:50 -08001274 ALOGV("copl(%x):out of compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001275 send_callback = true;
1276 event = STREAM_CBK_EVENT_WRITE_READY;
1277 break;
1278 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001279 ret = compress_next_track(out->compr);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301280 if(ret == 0) {
Steve Kondik05c17962015-02-25 00:55:50 -08001281 ALOGV("copl(%p):calling compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301282 ret = compress_partial_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001283 ALOGV("copl(%p):out of compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301284 if (ret < 0)
1285 ret = -errno;
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301286 }
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301287 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001288 compress_drain(out->compr);
1289 else
1290 ALOGE("%s: Next track returned error %d",__func__, ret);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301291
1292 if (ret != -ENETRESET) {
1293 send_callback = true;
1294 event = STREAM_CBK_EVENT_DRAIN_READY;
1295
1296 /* Resend the metadata for next iteration */
1297 out->send_new_metadata = 1;
1298 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1299 } else
1300 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001301 break;
1302 case OFFLOAD_CMD_DRAIN:
Steve Kondik05c17962015-02-25 00:55:50 -08001303 ALOGV("copl(%x):calling compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001304 compress_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001305 ALOGV("copl(%x):out of compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001306 send_callback = true;
1307 event = STREAM_CBK_EVENT_DRAIN_READY;
1308 break;
1309 default:
1310 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1311 break;
1312 }
1313 pthread_mutex_lock(&out->lock);
1314 out->offload_thread_blocked = false;
1315 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001316 if (send_callback) {
Ravi Kumar Alamanda3d316172014-12-02 19:21:51 -08001317 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001318 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001319 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001320 free(cmd);
1321 }
1322
1323 pthread_cond_signal(&out->cond);
1324 while (!list_empty(&out->offload_cmd_list)) {
1325 item = list_head(&out->offload_cmd_list);
1326 list_remove(item);
1327 free(node_to_item(item, struct offload_cmd, node));
1328 }
1329 pthread_mutex_unlock(&out->lock);
1330
1331 return NULL;
1332}
1333
1334static int create_offload_callback_thread(struct stream_out *out)
1335{
1336 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1337 list_init(&out->offload_cmd_list);
1338 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1339 offload_thread_loop, out);
1340 return 0;
1341}
1342
1343static int destroy_offload_callback_thread(struct stream_out *out)
1344{
1345 pthread_mutex_lock(&out->lock);
1346 stop_compressed_output_l(out);
1347 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1348
1349 pthread_mutex_unlock(&out->lock);
1350 pthread_join(out->offload_thread, (void **) NULL);
1351 pthread_cond_destroy(&out->offload_cond);
1352
1353 return 0;
1354}
1355
Eric Laurent07eeafd2013-10-06 12:52:49 -07001356static bool allow_hdmi_channel_config(struct audio_device *adev)
1357{
1358 struct listnode *node;
1359 struct audio_usecase *usecase;
1360 bool ret = true;
1361
1362 list_for_each(node, &adev->usecase_list) {
1363 usecase = node_to_item(node, struct audio_usecase, list);
1364 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1365 /*
1366 * If voice call is already existing, do not proceed further to avoid
1367 * disabling/enabling both RX and TX devices, CSD calls, etc.
1368 * Once the voice call done, the HDMI channels can be configured to
1369 * max channels of remaining use cases.
1370 */
1371 if (usecase->id == USECASE_VOICE_CALL) {
1372 ALOGD("%s: voice call is active, no change in HDMI channels",
1373 __func__);
1374 ret = false;
1375 break;
1376 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1377 ALOGD("%s: multi channel playback is active, "
1378 "no change in HDMI channels", __func__);
1379 ret = false;
1380 break;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001381 } else if (is_offload_usecase(usecase->id) &&
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301382 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin3ed162b2014-02-24 17:56:01 -08001383 ALOGD("%s: multi-channel(%x) compress offload playback is active, "
1384 "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
1385 ret = false;
1386 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001387 }
1388 }
1389 }
1390 return ret;
1391}
1392
1393static int check_and_set_hdmi_channels(struct audio_device *adev,
1394 unsigned int channels)
1395{
1396 struct listnode *node;
1397 struct audio_usecase *usecase;
1398
1399 /* Check if change in HDMI channel config is allowed */
1400 if (!allow_hdmi_channel_config(adev))
1401 return 0;
1402
1403 if (channels == adev->cur_hdmi_channels) {
Mingming Yin10fef6a2013-11-26 17:17:01 -08001404 ALOGD("%s: Requested channels are same as current channels(%d)", __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001405 return 0;
1406 }
1407
1408 platform_set_hdmi_channels(adev->platform, channels);
1409 adev->cur_hdmi_channels = channels;
1410
1411 /*
1412 * Deroute all the playback streams routed to HDMI so that
1413 * the back end is deactivated. Note that backend will not
1414 * be deactivated if any one stream is connected to it.
1415 */
1416 list_for_each(node, &adev->usecase_list) {
1417 usecase = node_to_item(node, struct audio_usecase, list);
1418 if (usecase->type == PCM_PLAYBACK &&
1419 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001420 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001421 }
1422 }
1423
1424 /*
1425 * Enable all the streams disabled above. Now the HDMI backend
1426 * will be activated with new channel configuration
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 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001433 }
1434 }
1435
1436 return 0;
1437}
1438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001439static int stop_output_stream(struct stream_out *out)
1440{
1441 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442 struct audio_usecase *uc_info;
1443 struct audio_device *adev = out->dev;
1444
Eric Laurent994a6932013-07-17 11:51:42 -07001445 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001446 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001447 uc_info = get_usecase_from_list(adev, out->usecase);
1448 if (uc_info == NULL) {
1449 ALOGE("%s: Could not find the usecase (%d) in the list",
1450 __func__, out->usecase);
1451 return -EINVAL;
1452 }
1453
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001454 if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001455 if (adev->visualizer_stop_output != NULL)
1456 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1457 if (adev->offload_effects_stop_output != NULL)
1458 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1459 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001460
Eric Laurent150dbfe2013-02-27 14:31:02 -08001461 /* 1. Get and set stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001462 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001463
1464 /* 2. Disable the rx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001465 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001466
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001467 list_remove(&uc_info->list);
1468 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001469
Eric Laurentda46bfb2014-08-25 22:39:29 -05001470 audio_extn_extspk_update(adev->extspk);
1471
Eric Laurent07eeafd2013-10-06 12:52:49 -07001472 /* Must be called after removing the usecase from list */
1473 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1474 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1475
Eric Laurent994a6932013-07-17 11:51:42 -07001476 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001477 return ret;
1478}
1479
1480int start_output_stream(struct stream_out *out)
1481{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482 int ret = 0;
Mingming Yin6c344432014-05-01 15:37:31 -07001483 int sink_channels = 0;
1484 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001485 struct audio_usecase *uc_info;
1486 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301487 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001488
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001489 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1490 ret = -EINVAL;
1491 goto error_config;
1492 }
1493
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301494 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1495 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1496 out->devices);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301497
Naresh Tannirucef332d2014-06-04 18:17:56 +05301498 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301499 ALOGE("%s: sound card is not active/SSR returning error", __func__);
1500 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301501 goto error_config;
1502 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301503
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301504 ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
1505 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001506 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001507 if (out->pcm_device_id < 0) {
1508 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1509 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001510 ret = -EINVAL;
1511 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001512 }
1513
1514 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001515
1516 if (!uc_info) {
1517 ret = -ENOMEM;
1518 goto error_config;
1519 }
1520
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521 uc_info->id = out->usecase;
1522 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001523 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001524 uc_info->devices = out->devices;
1525 uc_info->in_snd_device = SND_DEVICE_NONE;
1526 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001527
Eric Laurent07eeafd2013-10-06 12:52:49 -07001528 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001529 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Mingming Yin6c344432014-05-01 15:37:31 -07001530 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1531 if (!strncmp("true", prop_value, 4)) {
1532 sink_channels = platform_edid_get_max_channels(out->dev->platform);
1533 ALOGD("%s: set HDMI channel count[%d] based on sink capability", __func__, sink_channels);
1534 check_and_set_hdmi_channels(adev, sink_channels);
1535 } else {
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001536 if (is_offload_usecase(out->usecase))
Mingming Yin6c344432014-05-01 15:37:31 -07001537 check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in);
1538 else
1539 check_and_set_hdmi_channels(adev, out->config.channels);
1540 }
Mingming Yin10fef6a2013-11-26 17:17:01 -08001541 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001542
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001543 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001544
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001545 select_devices(adev, out->usecase);
1546
Eric Laurentda46bfb2014-08-25 22:39:29 -05001547 audio_extn_extspk_update(adev->extspk);
1548
Steve Kondik3abbbc82014-11-29 14:14:43 -08001549 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1550 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
1551
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001552 if (!is_offload_usecase(out->usecase)) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301553 unsigned int flags = PCM_OUT;
1554 unsigned int pcm_open_retry_count = 0;
1555 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1556 flags |= PCM_MMAP | PCM_NOIRQ;
1557 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1558 } else
1559 flags |= PCM_MONOTONIC;
1560
1561 while (1) {
1562 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1563 flags, &out->config);
1564 if (out->pcm && !pcm_is_ready(out->pcm)) {
1565 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1566 if (out->pcm != NULL) {
1567 pcm_close(out->pcm);
1568 out->pcm = NULL;
1569 }
1570 if (pcm_open_retry_count-- == 0) {
1571 ret = -EIO;
1572 goto error_open;
1573 }
1574 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1575 continue;
1576 }
1577 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001578 }
1579 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001580 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001581 out->compr = compress_open(adev->snd_card,
1582 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001583 COMPRESS_IN, &out->compr_config);
1584 if (out->compr && !is_compress_ready(out->compr)) {
1585 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1586 compress_close(out->compr);
1587 out->compr = NULL;
1588 ret = -EIO;
1589 goto error_open;
1590 }
1591 if (out->offload_callback)
1592 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001593
Fred Oh1483d8a2015-03-04 18:42:34 -08001594 /* Since small bufs uses blocking writes, a write will be blocked
1595 for the default max poll time (20s) in the event of an SSR.
1596 Reduce the poll time to observe and deal with SSR faster.
1597 */
1598 if (out->use_small_bufs) {
1599 compress_set_max_poll_wait(out->compr, 1000);
1600 }
1601
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08001602#ifdef DS1_DOLBY_DDP_ENABLED
1603 if (audio_extn_is_dolby_format(out->format))
1604 audio_extn_dolby_send_ddp_endp_params(adev);
1605#endif
1606
Eric Laurentc4aef752013-09-12 17:45:53 -07001607 if (adev->visualizer_start_output != NULL)
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001608 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1609 if (adev->offload_effects_start_output != NULL)
1610 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001611 }
Eric Laurent994a6932013-07-17 11:51:42 -07001612 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001613 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001614error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001615 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001616error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001617 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001618}
1619
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001620static int check_input_parameters(uint32_t sample_rate,
1621 audio_format_t format,
1622 int channel_count)
1623{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001624 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001625
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001626 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001627 !voice_extn_compress_voip_is_format_supported(format) &&
1628 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001629
1630 switch (channel_count) {
1631 case 1:
1632 case 2:
1633 case 6:
1634 break;
1635 default:
1636 ret = -EINVAL;
1637 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638
1639 switch (sample_rate) {
1640 case 8000:
1641 case 11025:
1642 case 12000:
1643 case 16000:
1644 case 22050:
1645 case 24000:
1646 case 32000:
1647 case 44100:
1648 case 48000:
1649 break;
1650 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001651 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001652 }
1653
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001654 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001655}
1656
1657static size_t get_input_buffer_size(uint32_t sample_rate,
1658 audio_format_t format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001659 int channel_count,
1660 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001661{
1662 size_t size = 0;
1663
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001664 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1665 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001666
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001667 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001668 if (is_low_latency)
1669 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001670 /* ToDo: should use frame_size computed based on the format and
1671 channel_count here. */
1672 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001674 /* make sure the size is multiple of 32 bytes
1675 * At 48 kHz mono 16-bit PCM:
1676 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1677 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1678 */
1679 size += 0x1f;
1680 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001681
1682 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001683}
1684
1685static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1686{
1687 struct stream_out *out = (struct stream_out *)stream;
1688
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001689 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001690}
1691
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301692static int out_set_sample_rate(struct audio_stream *stream __unused,
1693 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001694{
1695 return -ENOSYS;
1696}
1697
1698static size_t out_get_buffer_size(const struct audio_stream *stream)
1699{
1700 struct stream_out *out = (struct stream_out *)stream;
1701
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001702 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001703 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001704 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1705 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001706
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301707 return out->config.period_size *
1708 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001709}
1710
1711static uint32_t out_get_channels(const struct audio_stream *stream)
1712{
1713 struct stream_out *out = (struct stream_out *)stream;
1714
1715 return out->channel_mask;
1716}
1717
1718static audio_format_t out_get_format(const struct audio_stream *stream)
1719{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001720 struct stream_out *out = (struct stream_out *)stream;
1721
1722 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001723}
1724
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301725static int out_set_format(struct audio_stream *stream __unused,
1726 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727{
1728 return -ENOSYS;
1729}
1730
1731static int out_standby(struct audio_stream *stream)
1732{
1733 struct stream_out *out = (struct stream_out *)stream;
1734 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001735
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301736 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1737 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001738 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1739 /* Ignore standby in case of voip call because the voip output
1740 * stream is closed in adev_close_output_stream()
1741 */
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301742 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001743 return 0;
1744 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001746 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001748 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07001749
1750 amplifier_output_stream_standby((struct audio_stream_out *) stream);
1751
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752 out->standby = true;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001753 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001754 if (out->pcm) {
1755 pcm_close(out->pcm);
1756 out->pcm = NULL;
1757 }
1758 } else {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301759 ALOGD("copl(%x):standby", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001760 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001761 out->gapless_mdata.encoder_delay = 0;
1762 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001763 if (out->compr != NULL) {
1764 compress_close(out->compr);
1765 out->compr = NULL;
1766 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001767 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001769 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770 }
1771 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001772 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 return 0;
1774}
1775
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301776static int out_dump(const struct audio_stream *stream __unused,
1777 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778{
1779 return 0;
1780}
1781
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001782static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1783{
1784 int ret = 0;
1785 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001786 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001787 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001788 tmp_mdata.encoder_delay = 0;
1789 tmp_mdata.encoder_padding = 0;
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001790
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001791 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001792 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001793 return -EINVAL;
1794 }
1795
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001796 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1797 if (ret >= 0) {
1798 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1799 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1800 ALOGV("ADTS format is set in offload mode");
1801 }
1802 out->send_new_metadata = 1;
1803 }
1804
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001805#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001806 if (out->format == AUDIO_FORMAT_FLAC) {
1807 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1808 if (ret >= 0) {
1809 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1810 out->send_new_metadata = 1;
1811 }
1812 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1813 if (ret >= 0) {
1814 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1815 out->send_new_metadata = 1;
1816 }
1817 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1818 if (ret >= 0) {
1819 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1820 out->send_new_metadata = 1;
1821 }
1822 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1823 if (ret >= 0) {
1824 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1825 out->send_new_metadata = 1;
1826 }
1827 }
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001828#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001829
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001830 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1831 if(ret >= 0)
1832 is_meta_data_params = true;
1833 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1834 if(ret >= 0 )
1835 is_meta_data_params = true;
1836 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1837 if(ret >= 0 )
1838 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001839 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1840 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001841 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001842 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001843 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001844 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1845 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001846 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001847 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001848 }
1849
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001850 if(!is_meta_data_params) {
1851 ALOGV("%s: Not gapless meta data params", __func__);
1852 return 0;
1853 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001854 out->gapless_mdata = tmp_mdata;
1855 out->send_new_metadata = 1;
1856 ALOGV("%s new encoder delay %u and padding %u", __func__,
1857 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1858
Steve Kondikba3b35d2014-07-18 01:49:48 -07001859 if(out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
1860 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
1861 if (ret >= 0) {
1862 out->compr_config.codec->format = atoi(value);
1863 }
1864 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
1865 if (ret >= 0) {
1866 out->compr_config.codec->options.wma.super_block_align = atoi(value);
1867 }
1868 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
1869 if (ret >= 0) {
1870 out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
1871 }
1872 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
1873 if (ret >= 0) {
1874 out->compr_config.codec->options.wma.channelmask = atoi(value);
1875 }
1876 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
1877 if (ret >= 0) {
1878 out->compr_config.codec->options.wma.encodeopt = atoi(value);
1879 }
1880 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
1881 if (ret >= 0) {
1882 out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
1883 }
1884 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
1885 if (ret >= 0) {
1886 out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
1887 }
1888 ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
1889 out->compr_config.codec->format,
1890 out->compr_config.codec->options.wma.super_block_align,
1891 out->compr_config.codec->options.wma.bits_per_sample,
1892 out->compr_config.codec->options.wma.channelmask,
1893 out->compr_config.codec->options.wma.encodeopt,
1894 out->compr_config.codec->options.wma.encodeopt1,
1895 out->compr_config.codec->options.wma.encodeopt2);
1896 }
1897
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001898 return 0;
1899}
1900
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301901static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1902{
1903 return out == adev->primary_output || out == adev->voice_tx_output;
1904}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001905
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1907{
1908 struct stream_out *out = (struct stream_out *)stream;
1909 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001910 struct audio_usecase *usecase;
1911 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912 struct str_parms *parms;
1913 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001914 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001915 bool select_new_device = false;
Steve Kondik3abbbc82014-11-29 14:14:43 -08001916 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001917
sangwoobc677242013-08-08 16:53:43 +09001918 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001919 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001920 parms = str_parms_create_str(kvpairs);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001921 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1922 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001923 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001925 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001926
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001927 /*
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301928 * When HDMI cable is unplugged/usb hs is disconnected the
1929 * music playback is paused and the policy manager sends routing=0
1930 * But the audioflingercontinues to write data until standby time
1931 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001932 * Avoid this by routing audio to speaker until standby.
1933 */
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301934 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
Steve Kondikeadb6c82014-09-03 18:40:06 -07001935 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
1936 out->devices == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001937 val == AUDIO_DEVICE_NONE) {
1938 val = AUDIO_DEVICE_OUT_SPEAKER;
1939 }
1940
1941 /*
1942 * select_devices() call below switches all the usecases on the same
1943 * backend to the new device. Refer to check_usecases_codec_backend() in
1944 * the select_devices(). But how do we undo this?
1945 *
1946 * For example, music playback is active on headset (deep-buffer usecase)
1947 * and if we go to ringtones and select a ringtone, low-latency usecase
1948 * will be started on headset+speaker. As we can't enable headset+speaker
1949 * and headset devices at the same time, select_devices() switches the music
1950 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1951 * So when the ringtone playback is completed, how do we undo the same?
1952 *
1953 * We are relying on the out_set_parameters() call on deep-buffer output,
1954 * once the ringtone playback is ended.
1955 * NOTE: We should not check if the current devices are same as new devices.
1956 * Because select_devices() must be called to switch back the music
1957 * playback to headset.
1958 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001959 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001960 out->devices = val;
1961
1962 if (!out->standby)
1963 select_devices(adev, out->usecase);
1964
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001965 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301966 output_drives_call(adev, out)) {
1967 adev->current_call_output = out;
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001968 if (!adev->voice.in_call)
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301969 ret = voice_start_call(adev);
1970 else
1971 voice_update_devices_for_all_voice_usecases(adev);
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001972 }
1973 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001974
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001975 if ((adev->mode == AUDIO_MODE_NORMAL) &&
1976 adev->voice.in_call &&
1977 output_drives_call(adev, out)) {
1978 ret = voice_stop_call(adev);
1979 adev->current_call_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001980 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001982 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001983 pthread_mutex_unlock(&out->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05001984
1985 /*handles device and call state changes*/
1986 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001987 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001988
1989 if (out == adev->primary_output) {
1990 pthread_mutex_lock(&adev->lock);
1991 audio_extn_set_parameters(adev, parms);
1992 pthread_mutex_unlock(&adev->lock);
1993 }
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001994 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001995 pthread_mutex_lock(&out->lock);
Steve Kondikba3b35d2014-07-18 01:49:48 -07001996 ret = parse_compress_metadata(out, parms);
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001997 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001998 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002001 ALOGV("%s: exit: code(%d)", __func__, status);
2002 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002003}
2004
2005static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2006{
2007 struct stream_out *out = (struct stream_out *)stream;
2008 struct str_parms *query = str_parms_create_str(keys);
2009 char *str;
2010 char value[256];
2011 struct str_parms *reply = str_parms_create();
2012 size_t i, j;
2013 int ret;
2014 bool first = true;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002015
2016 if (!query || !reply) {
2017 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2018 return NULL;
2019 }
2020
Eric Laurent994a6932013-07-17 11:51:42 -07002021 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2023 if (ret >= 0) {
2024 value[0] = '\0';
2025 i = 0;
2026 while (out->supported_channel_masks[i] != 0) {
2027 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2028 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2029 if (!first) {
2030 strcat(value, "|");
2031 }
2032 strcat(value, out_channels_name_to_enum_table[j].name);
2033 first = false;
2034 break;
2035 }
2036 }
2037 i++;
2038 }
2039 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2040 str = str_parms_to_str(reply);
2041 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002042 voice_extn_out_get_parameters(out, query, reply);
2043 str = str_parms_to_str(reply);
2044 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella2e032352014-01-29 12:52:19 -08002045 free(str);
2046 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002047 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002048 }
2049 str_parms_destroy(query);
2050 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002051 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002052 return str;
2053}
2054
2055static uint32_t out_get_latency(const struct audio_stream_out *stream)
2056{
2057 struct stream_out *out = (struct stream_out *)stream;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002058 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002059
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002060 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002061 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002062 } else {
2063 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002064 (out->config.rate);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002065 }
2066
Anish Kumar1a0594f2014-12-09 04:01:39 +05302067 ALOGV("%s: Latency %d", __func__, latency);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002068 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002069}
2070
2071static int out_set_volume(struct audio_stream_out *stream, float left,
2072 float right)
2073{
Eric Laurenta9024de2013-04-04 09:19:12 -07002074 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002075 int volume[2];
2076
Eric Laurenta9024de2013-04-04 09:19:12 -07002077 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2078 /* only take left channel into account: the API is for stereo anyway */
2079 out->muted = (left == 0.0f);
2080 return 0;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002081 } else if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002082 char mixer_ctl_name[128];
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002083 struct audio_device *adev = out->dev;
2084 struct mixer_ctl *ctl;
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002085 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2086 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002087
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002088 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2089 "Compress Playback %d Volume", pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002090 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2091 if (!ctl) {
2092 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2093 __func__, mixer_ctl_name);
2094 return -EINVAL;
2095 }
2096 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2097 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2098 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2099 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002100 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 return -ENOSYS;
2103}
2104
2105static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2106 size_t bytes)
2107{
2108 struct stream_out *out = (struct stream_out *)stream;
2109 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302110 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002111 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113 pthread_mutex_lock(&out->lock);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302114
Naresh Tannirucef332d2014-06-04 18:17:56 +05302115 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
2116 if (out->pcm) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302117 ALOGD(" %s: sound card is not active/SSR state", __func__);
2118 ret= -ENETRESET;
2119 goto exit;
Alexy Joseph55204352014-10-06 12:15:01 -07002120 } else if (is_offload_usecase(out->usecase)) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302121 //during SSR for compress usecase we should return error to flinger
2122 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2123 pthread_mutex_unlock(&out->lock);
2124 return -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302125 }
2126 }
2127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002128 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002129 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002130 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002131 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2132 ret = voice_extn_compress_voip_start_output_stream(out);
2133 else
2134 ret = start_output_stream(out);
Ethan Chen79c356c2015-06-07 12:26:14 -07002135
2136 if (ret == 0)
2137 amplifier_output_stream_start(stream,
2138 is_offload_usecase(out->usecase));
2139
Eric Laurent150dbfe2013-02-27 14:31:02 -08002140 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002141 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002142 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002143 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002144 goto exit;
2145 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002147
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002148 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002149 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002150 if (out->send_new_metadata) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302151 ALOGD("copl(%x):send new gapless metadata", (unsigned int)out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002152 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2153 out->send_new_metadata = 0;
2154 }
2155
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002156 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302157 if (ret < 0)
2158 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002159 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002160 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302161 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002162 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302163 } else if (-ENETRESET == ret) {
2164 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2165 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2166 pthread_mutex_unlock(&out->lock);
2167 out_standby(&out->stream.common);
2168 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002169 }
Naresh Tannirucef332d2014-06-04 18:17:56 +05302170 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002171 compress_start(out->compr);
2172 out->playback_started = 1;
2173 out->offload_state = OFFLOAD_STATE_PLAYING;
2174 }
2175 pthread_mutex_unlock(&out->lock);
2176 return ret;
2177 } else {
2178 if (out->pcm) {
2179 if (out->muted)
2180 memset((void *)buffer, 0, bytes);
2181 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302182 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2183 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2184 else
2185 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302186 if (ret < 0)
2187 ret = -errno;
2188 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002189 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002190 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191 }
2192
2193exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302194 /* ToDo: There may be a corner case when SSR happens back to back during
2195 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302196 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302197 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302198 }
2199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002200 pthread_mutex_unlock(&out->lock);
2201
2202 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002203 if (out->pcm)
2204 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302205 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302206 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302207 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302208 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302209 out->standby = true;
2210 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002211 out_standby(&out->stream.common);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002212 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
2213 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002214 }
2215 return bytes;
2216}
2217
2218static int out_get_render_position(const struct audio_stream_out *stream,
2219 uint32_t *dsp_frames)
2220{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002221 struct stream_out *out = (struct stream_out *)stream;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002222 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
2223 ssize_t ret = 0;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002224 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002225 pthread_mutex_lock(&out->lock);
2226 if (out->compr != NULL) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302227 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002228 &out->sample_rate);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302229 if (ret < 0)
2230 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002231 ALOGVV("%s rendered frames %d sample_rate %d",
2232 __func__, *dsp_frames, out->sample_rate);
2233 }
2234 pthread_mutex_unlock(&out->lock);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302235 if (-ENETRESET == ret) {
2236 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2237 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2238 return -EINVAL;
2239 } else if(ret < 0) {
Steve Kondik81506242014-07-21 16:12:57 -07002240 if (out->compr == NULL) {
2241 return 0;
2242 }
2243 ALOGE(" ERROR: Unable to get time stamp from compress driver ret=%d", ret);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302244 return -EINVAL;
2245 } else {
2246 return 0;
2247 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002248 } else
2249 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250}
2251
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302252static int out_add_audio_effect(const struct audio_stream *stream __unused,
2253 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002254{
2255 return 0;
2256}
2257
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302258static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2259 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002260{
2261 return 0;
2262}
2263
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302264static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2265 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002266{
2267 return -EINVAL;
2268}
2269
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002270static int out_get_presentation_position(const struct audio_stream_out *stream,
2271 uint64_t *frames, struct timespec *timestamp)
2272{
2273 struct stream_out *out = (struct stream_out *)stream;
2274 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002275 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002276
2277 pthread_mutex_lock(&out->lock);
2278
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002279 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002280 if (out->compr != NULL) {
2281 compress_get_tstamp(out->compr, &dsp_frames,
2282 &out->sample_rate);
2283 ALOGVV("%s rendered frames %ld sample_rate %d",
2284 __func__, dsp_frames, out->sample_rate);
2285 *frames = dsp_frames;
2286 ret = 0;
2287 /* this is the best we can do */
2288 clock_gettime(CLOCK_MONOTONIC, timestamp);
2289 }
2290 } else {
2291 if (out->pcm) {
2292 size_t avail;
2293 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2294 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002295 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002296 // This adjustment accounts for buffering after app processor.
2297 // It is based on estimated DSP latency per use case, rather than exact.
2298 signed_frames -=
2299 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2300
Eric Laurent949a0892013-09-20 09:20:13 -07002301 // It would be unusual for this value to be negative, but check just in case ...
2302 if (signed_frames >= 0) {
2303 *frames = signed_frames;
2304 ret = 0;
2305 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002306 }
2307 }
2308 }
2309
2310 pthread_mutex_unlock(&out->lock);
2311
2312 return ret;
2313}
2314
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315static int out_set_callback(struct audio_stream_out *stream,
2316 stream_callback_t callback, void *cookie)
2317{
2318 struct stream_out *out = (struct stream_out *)stream;
2319
2320 ALOGV("%s", __func__);
2321 pthread_mutex_lock(&out->lock);
2322 out->offload_callback = callback;
2323 out->offload_cookie = cookie;
2324 pthread_mutex_unlock(&out->lock);
2325 return 0;
2326}
2327
2328static int out_pause(struct audio_stream_out* stream)
2329{
2330 struct stream_out *out = (struct stream_out *)stream;
2331 int status = -ENOSYS;
2332 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002333 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302334 ALOGD("copl(%x):pause compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002335 pthread_mutex_lock(&out->lock);
2336 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302337 struct audio_device *adev = out->dev;
2338 int snd_scard_state = get_snd_card_state(adev);
2339
2340 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2341 status = compress_pause(out->compr);
2342
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 out->offload_state = OFFLOAD_STATE_PAUSED;
2344 }
2345 pthread_mutex_unlock(&out->lock);
2346 }
2347 return status;
2348}
2349
2350static int out_resume(struct audio_stream_out* stream)
2351{
2352 struct stream_out *out = (struct stream_out *)stream;
2353 int status = -ENOSYS;
2354 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002355 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302356 ALOGD("copl(%x):resume compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002357 status = 0;
2358 pthread_mutex_lock(&out->lock);
2359 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302360 struct audio_device *adev = out->dev;
2361 int snd_scard_state = get_snd_card_state(adev);
2362
2363 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2364 status = compress_resume(out->compr);
2365
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002366 out->offload_state = OFFLOAD_STATE_PLAYING;
2367 }
2368 pthread_mutex_unlock(&out->lock);
2369 }
2370 return status;
2371}
2372
2373static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2374{
2375 struct stream_out *out = (struct stream_out *)stream;
2376 int status = -ENOSYS;
2377 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002378 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002379 pthread_mutex_lock(&out->lock);
2380 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2381 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2382 else
2383 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2384 pthread_mutex_unlock(&out->lock);
2385 }
2386 return status;
2387}
2388
2389static int out_flush(struct audio_stream_out* stream)
2390{
2391 struct stream_out *out = (struct stream_out *)stream;
2392 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002393 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302394 ALOGD("copl(%x):calling compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002395 pthread_mutex_lock(&out->lock);
2396 stop_compressed_output_l(out);
2397 pthread_mutex_unlock(&out->lock);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302398 ALOGD("copl(%x):out of compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002399 return 0;
2400 }
2401 return -ENOSYS;
2402}
2403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002404/** audio_stream_in implementation **/
2405static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2406{
2407 struct stream_in *in = (struct stream_in *)stream;
2408
2409 return in->config.rate;
2410}
2411
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302412static int in_set_sample_rate(struct audio_stream *stream __unused,
2413 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002414{
2415 return -ENOSYS;
2416}
2417
2418static size_t in_get_buffer_size(const struct audio_stream *stream)
2419{
2420 struct stream_in *in = (struct stream_in *)stream;
2421
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002422 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2423 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002424 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2425 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002426
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302427 return in->config.period_size *
Steve Kondik3abbbc82014-11-29 14:14:43 -08002428 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002429}
2430
2431static uint32_t in_get_channels(const struct audio_stream *stream)
2432{
2433 struct stream_in *in = (struct stream_in *)stream;
2434
2435 return in->channel_mask;
2436}
2437
2438static audio_format_t in_get_format(const struct audio_stream *stream)
2439{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002440 struct stream_in *in = (struct stream_in *)stream;
2441
2442 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002443}
2444
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302445static int in_set_format(struct audio_stream *stream __unused,
2446 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447{
2448 return -ENOSYS;
2449}
2450
2451static int in_standby(struct audio_stream *stream)
2452{
2453 struct stream_in *in = (struct stream_in *)stream;
2454 struct audio_device *adev = in->dev;
2455 int status = 0;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302456 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2457 stream, in->usecase, use_case_table[in->usecase]);
2458
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002459
2460 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2461 /* Ignore standby in case of voip call because the voip input
2462 * stream is closed in adev_close_input_stream()
2463 */
2464 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2465 return status;
2466 }
2467
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002468 pthread_mutex_lock(&in->lock);
2469 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002470 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07002471
2472 amplifier_input_stream_standby((struct audio_stream_in *) stream);
2473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002474 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002475 if (in->pcm) {
2476 pcm_close(in->pcm);
2477 in->pcm = NULL;
2478 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002479 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002480 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002481 }
2482 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002483 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002484 return status;
2485}
2486
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302487static int in_dump(const struct audio_stream *stream __unused,
2488 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002489{
2490 return 0;
2491}
2492
2493static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2494{
2495 struct stream_in *in = (struct stream_in *)stream;
2496 struct audio_device *adev = in->dev;
2497 struct str_parms *parms;
2498 char *str;
2499 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002500 int ret = 0, val = 0, err;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002501 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302503 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 parms = str_parms_create_str(kvpairs);
2505
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002507 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002508
2509 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2510 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002511 val = atoi(value);
2512 /* no audio source uses val == 0 */
2513 if ((in->source != val) && (val != 0)) {
2514 in->source = val;
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002515 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2516 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2517 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2518 (in->config.rate == 8000 || in->config.rate == 16000) &&
Steve Kondikb6ab1fa2015-02-06 16:55:26 -08002519 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002520 err = voice_extn_compress_voip_open_input_stream(in);
2521 if (err != 0) {
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002522 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002523 __func__, err);
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002524 }
2525 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 }
2527 }
2528
Steve Kondik3abbbc82014-11-29 14:14:43 -08002529 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2530
2531 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532 val = atoi(value);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302533 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002534 in->device = val;
2535 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002536 if (!in->standby)
Steve Kondik3abbbc82014-11-29 14:14:43 -08002537 status = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002538 }
2539 }
2540
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002541done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002542 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002543 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544
2545 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002546 ALOGV("%s: exit: status(%d)", __func__, status);
2547 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002548}
2549
2550static char* in_get_parameters(const struct audio_stream *stream,
2551 const char *keys)
2552{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002553 struct stream_in *in = (struct stream_in *)stream;
2554 struct str_parms *query = str_parms_create_str(keys);
2555 char *str;
2556 char value[256];
2557 struct str_parms *reply = str_parms_create();
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002558
2559 if (!query || !reply) {
2560 ALOGE("in_get_parameters: failed to create query or reply");
2561 return NULL;
2562 }
2563
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002564 ALOGV("%s: enter: keys - %s", __func__, keys);
2565
2566 voice_extn_in_get_parameters(in, query, reply);
2567
2568 str = str_parms_to_str(reply);
2569 str_parms_destroy(query);
2570 str_parms_destroy(reply);
2571
2572 ALOGV("%s: exit: returns - %s", __func__, str);
2573 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002574}
2575
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302576static int in_set_gain(struct audio_stream_in *stream __unused,
2577 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578{
2579 return 0;
2580}
2581
2582static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2583 size_t bytes)
2584{
2585 struct stream_in *in = (struct stream_in *)stream;
2586 struct audio_device *adev = in->dev;
2587 int i, ret = -1;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302588 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590 pthread_mutex_lock(&in->lock);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302591
2592 if (in->pcm) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302593 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302594 ALOGD(" %s: sound card is not active/SSR state", __func__);
2595 ret= -ENETRESET;
2596 goto exit;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302597 }
2598 }
2599
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002601 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002602 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2603 ret = voice_extn_compress_voip_start_input_stream(in);
2604 else
2605 ret = start_input_stream(in);
Ethan Chen79c356c2015-06-07 12:26:14 -07002606
2607 if (ret == 0)
2608 amplifier_input_stream_start(stream);
2609
Eric Laurent150dbfe2013-02-27 14:31:02 -08002610 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002612 goto exit;
2613 }
2614 in->standby = 0;
2615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616
2617 if (in->pcm) {
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302618 if (audio_extn_ssr_get_enabled() &&
2619 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002620 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002621 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2622 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302623 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2624 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002625 else
2626 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302627 if (ret < 0)
2628 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 }
2630
2631 /*
2632 * Instead of writing zeroes here, we could trust the hardware
2633 * to always provide zeroes when muted.
2634 */
Pavan Chikkala6c183fd2014-12-04 10:48:28 +05302635 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2636 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002637 memset(buffer, 0, bytes);
2638
2639exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302640 /* ToDo: There may be a corner case when SSR happens back to back during
2641 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302642 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302643 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302644 memset(buffer, 0, bytes);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302645 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002646 pthread_mutex_unlock(&in->lock);
2647
2648 if (ret != 0) {
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302649 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302650 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302651 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302652 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302653 in->standby = true;
2654 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 in_standby(&in->stream.common);
2656 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002657 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
2658 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 }
2660 return bytes;
2661}
2662
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302663static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664{
2665 return 0;
2666}
2667
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002668static int add_remove_audio_effect(const struct audio_stream *stream,
2669 effect_handle_t effect,
2670 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002671{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002672 struct stream_in *in = (struct stream_in *)stream;
2673 int status = 0;
2674 effect_descriptor_t desc;
2675
2676 status = (*effect)->get_descriptor(effect, &desc);
2677 if (status != 0)
2678 return status;
2679
2680 pthread_mutex_lock(&in->lock);
2681 pthread_mutex_lock(&in->dev->lock);
2682 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2683 in->enable_aec != enable &&
2684 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2685 in->enable_aec = enable;
2686 if (!in->standby)
2687 select_devices(in->dev, in->usecase);
2688 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002689 if (in->enable_ns != enable &&
2690 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2691 in->enable_ns = enable;
2692 if (!in->standby)
2693 select_devices(in->dev, in->usecase);
2694 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002695 pthread_mutex_unlock(&in->dev->lock);
2696 pthread_mutex_unlock(&in->lock);
2697
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698 return 0;
2699}
2700
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002701static int in_add_audio_effect(const struct audio_stream *stream,
2702 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703{
Eric Laurent994a6932013-07-17 11:51:42 -07002704 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002705 return add_remove_audio_effect(stream, effect, true);
2706}
2707
2708static int in_remove_audio_effect(const struct audio_stream *stream,
2709 effect_handle_t effect)
2710{
Eric Laurent994a6932013-07-17 11:51:42 -07002711 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002712 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002713}
2714
2715static int adev_open_output_stream(struct audio_hw_device *dev,
2716 audio_io_handle_t handle,
2717 audio_devices_t devices,
2718 audio_output_flags_t flags,
2719 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302720 struct audio_stream_out **stream_out,
2721 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722{
2723 struct audio_device *adev = (struct audio_device *)dev;
2724 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002725 int i, ret = 0;
Steve Kondik5a447012014-12-02 16:04:20 -08002726 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002727
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002728 *stream_out = NULL;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302729
2730 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2731 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2732 ALOGE(" sound card is not active rejecting compress output open request");
2733 return -EINVAL;
2734 }
2735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2737
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302738 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2739 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2740 devices, flags, &out->stream);
2741
2742
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002743 if (!out) {
2744 return -ENOMEM;
2745 }
2746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 if (devices == AUDIO_DEVICE_NONE)
2748 devices = AUDIO_DEVICE_OUT_SPEAKER;
2749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002750 out->flags = flags;
2751 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002752 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002753 out->format = config->format;
2754 out->sample_rate = config->sample_rate;
2755 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2756 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002757 out->handle = handle;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002758 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002759 out->non_blocking = 0;
2760 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002761
2762 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002763 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
Mingming Yinee733602014-04-03 17:47:22 -07002764 (
2765#ifdef AFE_PROXY_ENABLED
2766 out->devices & AUDIO_DEVICE_OUT_PROXY ||
2767#endif
2768 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002769
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002770 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002771 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2772 ret = read_hdmi_channel_masks(out);
2773
Mingming Yinee733602014-04-03 17:47:22 -07002774#ifdef AFE_PROXY_ENABLED
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002775 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2776 ret = audio_extn_read_afe_proxy_channel_masks(out);
Mingming Yinee733602014-04-03 17:47:22 -07002777#endif
2778
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002779 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002780 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002781 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002782
2783 if (config->sample_rate == 0)
2784 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2785 if (config->channel_mask == 0)
2786 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2787
2788 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002789 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002790 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2791 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792 out->config.rate = config->sample_rate;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302793 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Mingming Yinee733602014-04-03 17:47:22 -07002795#ifdef COMPRESS_VOIP_ENABLED
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002796 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2797 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002798 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002799 ret = voice_extn_compress_voip_open_output_stream(out);
2800 if (ret != 0) {
2801 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2802 __func__, ret);
2803 goto error_open;
2804 }
Mingming Yinee733602014-04-03 17:47:22 -07002805#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002806 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302807 ALOGD("%s: copl(%x): sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
2808 __func__, (unsigned int)out, config->sample_rate, config->channel_mask, devices, flags);
2809
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002810 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2811 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2812 ALOGE("%s: Unsupported Offload information", __func__);
2813 ret = -EINVAL;
2814 goto error_open;
2815 }
Mingming Yin90310102013-11-13 16:57:00 -08002816 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002817 !audio_extn_is_dolby_format(config->offload_info.format)) {
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002818 ALOGE("%s: Unsupported offload audio format %x", __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002819 ret = -EINVAL;
2820 goto error_open;
2821 }
2822
2823 out->compr_config.codec = (struct snd_codec *)
2824 calloc(1, sizeof(struct snd_codec));
2825
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002826 if (!out->compr_config.codec) {
2827 ret = -ENOMEM;
2828 goto error_open;
2829 }
2830
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002831 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 if (config->offload_info.channel_mask)
2833 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002834 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 out->channel_mask = config->channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002836 config->offload_info.channel_mask = config->channel_mask;
2837 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002838 out->format = config->offload_info.format;
2839 out->sample_rate = config->offload_info.sample_rate;
2840
2841 out->stream.set_callback = out_set_callback;
2842 out->stream.pause = out_pause;
2843 out->stream.resume = out_resume;
2844 out->stream.drain = out_drain;
2845 out->stream.flush = out_flush;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002846 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002847
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002848 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002849 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002850 audio_extn_dolby_get_snd_codec_id(adev, out,
2851 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002852 else
2853 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002854 get_snd_codec_id(config->offload_info.format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002855
ApurupaPattapu0c566872014-01-10 14:46:02 -08002856 if (audio_is_offload_pcm(config->offload_info.format)) {
2857 out->compr_config.fragment_size =
2858 platform_get_pcm_offload_buffer_size(&config->offload_info);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002859 } else {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002860 out->compr_config.fragment_size =
2861 platform_get_compress_offload_buffer_size(&config->offload_info);
2862 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002863 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
2864 out->compr_config.codec->sample_rate =
2865 compress_get_alsa_rate(config->offload_info.sample_rate);
2866 out->compr_config.codec->bit_rate =
2867 config->offload_info.bit_rate;
2868 out->compr_config.codec->ch_in =
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302869 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002871 out->bit_width = config->offload_info.bit_width;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002873 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
Steve Kondik37454012014-11-23 19:54:21 -08002874 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002875 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2876 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002877
Steve Kondik3abbbc82014-11-29 14:14:43 -08002878 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002879 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002880
Steve Kondik3abbbc82014-11-29 14:14:43 -08002881 if (out->bit_width == 24)
2882 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002883
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002884#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik37454012014-11-23 19:54:21 -08002885 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
2886 out->compr_config.codec->options.flac_dec.sample_size = config->offload_info.bit_width;
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002887#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002888
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2890 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002891
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002892 if (config->offload_info.use_small_bufs) {
2893 //this flag is set from framework only if its for PCM formats
2894 //no need to check for PCM format again
2895 out->non_blocking = 0;
2896 out->use_small_bufs = true;
2897 ALOGI("Keep write blocking for small buff: non_blockling %d",
2898 out->non_blocking);
2899 }
2900
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002901 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002902 out->offload_state = OFFLOAD_STATE_IDLE;
2903 out->playback_started = 0;
2904
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002905 create_offload_callback_thread(out);
2906 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2907 __func__, config->offload_info.version,
2908 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002909 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -08002910 check_and_set_gapless_mode(adev);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002911
Mingming Yinee733602014-04-03 17:47:22 -07002912#ifdef INCALL_MUSIC_ENABLED
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002913 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2914 ret = voice_check_and_set_incall_music_usecase(adev, out);
2915 if (ret != 0) {
2916 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2917 __func__, ret);
2918 goto error_open;
2919 }
Mingming Yinee733602014-04-03 17:47:22 -07002920#endif
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302921 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2922 if (config->sample_rate == 0)
2923 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2924 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2925 config->sample_rate != 8000) {
2926 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2927 ret = -EINVAL;
2928 goto error_open;
2929 }
2930 out->sample_rate = config->sample_rate;
2931 out->config.rate = config->sample_rate;
2932 if (config->format == AUDIO_FORMAT_DEFAULT)
2933 config->format = AUDIO_FORMAT_PCM_16_BIT;
2934 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2935 config->format = AUDIO_FORMAT_PCM_16_BIT;
2936 ret = -EINVAL;
2937 goto error_open;
2938 }
2939 out->format = config->format;
2940 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2941 out->config = pcm_config_afe_proxy_playback;
2942 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002943 } else {
Steve Kondik3abbbc82014-11-29 14:14:43 -08002944#ifndef LOW_LATENCY_PRIMARY
2945 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
2946 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2947 out->config = pcm_config_low_latency;
Steve Kondikb045f472014-11-12 23:24:07 -08002948#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -08002949#ifdef LOW_LATENCY_PRIMARY
2950 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2951 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2952 out->config = pcm_config_deep_buffer;
2953#endif
2954 } else {
2955 /* primary path is the default path selected if no other outputs are available/suitable */
2956 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
2957#ifdef LOW_LATENCY_PRIMARY
2958 out->config = pcm_config_low_latency;
2959#else
2960 out->config = pcm_config_deep_buffer;
2961#endif
2962 }
2963 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2964 if (k_enable_extended_precision
2965 && pcm_params_format_test(adev->use_case_table[out->usecase],
2966 pcm_format_from_audio_format(config->format))) {
2967 out->config.format = pcm_format_from_audio_format(config->format);
2968 /* out->format already set to config->format */
2969 } else {
2970 /* deny the externally proposed config format
2971 * and use the one specified in audio_hw layer configuration.
2972 * Note: out->format is returned by out->stream.common.get_format()
2973 * and is used to set config->format in the code several lines below.
2974 */
Steve Kondik5a447012014-12-02 16:04:20 -08002975 ALOGW("Audio format %x is not available on this output", out->format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002976 out->format = audio_format_from_pcm_format(out->config.format);
2977 }
2978 }
2979
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002980 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002981 }
2982
Steve Kondik5a447012014-12-02 16:04:20 -08002983 ALOGV("%s flags %x, format %x, sample_rate %d, out->bit_width %d",
2984 __func__, flags, out->format, out->sample_rate, out->bit_width);
2985
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002986 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
Steve Kondik3abbbc82014-11-29 14:14:43 -08002987 flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002988 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002989 if(adev->primary_output == NULL)
2990 adev->primary_output = out;
2991 else {
2992 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002993 ret = -EEXIST;
2994 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002995 }
2996 }
2997
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002998 /* Check if this usecase is already existing */
2999 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella0d06c8e2014-04-17 20:00:41 -07003000 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3001 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003002 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003004 ret = -EEXIST;
3005 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003006 }
3007 pthread_mutex_unlock(&adev->lock);
3008
3009 out->stream.common.get_sample_rate = out_get_sample_rate;
3010 out->stream.common.set_sample_rate = out_set_sample_rate;
3011 out->stream.common.get_buffer_size = out_get_buffer_size;
3012 out->stream.common.get_channels = out_get_channels;
3013 out->stream.common.get_format = out_get_format;
3014 out->stream.common.set_format = out_set_format;
3015 out->stream.common.standby = out_standby;
3016 out->stream.common.dump = out_dump;
3017 out->stream.common.set_parameters = out_set_parameters;
3018 out->stream.common.get_parameters = out_get_parameters;
3019 out->stream.common.add_audio_effect = out_add_audio_effect;
3020 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3021 out->stream.get_latency = out_get_latency;
3022 out->stream.set_volume = out_set_volume;
3023 out->stream.write = out_write;
3024 out->stream.get_render_position = out_get_render_position;
3025 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003026 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003029 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003030 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003031
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303032 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3033 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003035 config->format = out->stream.common.get_format(&out->stream.common);
3036 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3037 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3038
3039 *stream_out = &out->stream;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303040 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3041 use_case_table[out->usecase]);
Eric Laurent994a6932013-07-17 11:51:42 -07003042 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003043 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003044
3045error_open:
3046 free(out);
3047 *stream_out = NULL;
3048 ALOGD("%s: exit: ret %d", __func__, ret);
3049 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050}
3051
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303052static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053 struct audio_stream_out *stream)
3054{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003055 struct stream_out *out = (struct stream_out *)stream;
3056 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003057 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003058
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303059 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3060
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003061 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303062 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003063 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303064 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003065 if(ret != 0)
3066 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3067 __func__, ret);
3068 }
3069 else
3070 out_standby(&stream->common);
3071
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003072 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003074 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003075 if (out->compr_config.codec != NULL)
3076 free(out->compr_config.codec);
3077 }
3078 pthread_cond_destroy(&out->cond);
3079 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003081 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082}
3083
Alexy Joseph55204352014-10-06 12:15:01 -07003084static void close_compress_sessions(struct audio_device *adev)
3085{
3086 struct stream_out *out = NULL;
3087 struct listnode *node = NULL;
3088 struct listnode *tmp = NULL;
3089 struct audio_usecase *usecase = NULL;
3090 pthread_mutex_lock(&adev->lock);
3091 list_for_each_safe(node, tmp, &adev->usecase_list) {
3092 usecase = node_to_item(node, struct audio_usecase, list);
3093 if (is_offload_usecase(usecase->id)) {
3094 if (usecase && usecase->stream.out) {
3095 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3096 out = usecase->stream.out;
3097 pthread_mutex_unlock(&adev->lock);
3098 out_standby(&out->stream.common);
3099 pthread_mutex_lock(&adev->lock);
3100 }
3101 }
3102 }
3103 pthread_mutex_unlock(&adev->lock);
3104}
3105
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3107{
3108 struct audio_device *adev = (struct audio_device *)dev;
3109 struct str_parms *parms;
3110 char *str;
3111 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003112 int val;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303113 int ret;
3114 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003116 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003117 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003118
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303119 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3120 if (ret >= 0) {
3121 char *snd_card_status = value+2;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303122 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05303123 struct listnode *node;
3124 struct audio_usecase *usecase;
3125
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303126 ALOGD("Received sound card OFFLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303127 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3128
Alexy Joseph55204352014-10-06 12:15:01 -07003129 //close compress sessions on OFFLINE status
3130 close_compress_sessions(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303131 } else if (strstr(snd_card_status, "ONLINE")) {
3132 ALOGD("Received sound card ONLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303133 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303134 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303135 }
3136
3137 pthread_mutex_lock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303138 status = voice_set_parameters(adev, parms);
3139 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003140 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003141
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303142 status = platform_set_parameters(adev->platform, parms);
3143 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003144 goto done;
3145
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303146 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3147 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 /* When set to false, HAL should disable EC and NS
3149 * But it is currently not supported.
3150 */
3151 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3152 adev->bluetooth_nrec = true;
3153 else
3154 adev->bluetooth_nrec = false;
3155 }
3156
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303157 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3158 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3160 adev->screen_off = false;
3161 else
3162 adev->screen_off = true;
3163 }
3164
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303165 ret = str_parms_get_int(parms, "rotation", &val);
3166 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003167 bool reverse_speakers = false;
3168 switch(val) {
3169 // FIXME: note that the code below assumes that the speakers are in the correct placement
3170 // relative to the user when the device is rotated 90deg from its default rotation. This
3171 // assumption is device-specific, not platform-specific like this code.
3172 case 270:
3173 reverse_speakers = true;
3174 break;
3175 case 0:
3176 case 90:
3177 case 180:
3178 break;
3179 default:
3180 ALOGE("%s: unexpected rotation of %d", __func__, val);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303181 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003182 }
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303183 if (status == 0) {
3184 if (adev->speaker_lr_swap != reverse_speakers) {
3185 adev->speaker_lr_swap = reverse_speakers;
3186 // only update the selected device if there is active pcm playback
3187 struct audio_usecase *usecase;
3188 struct listnode *node;
3189 list_for_each(node, &adev->usecase_list) {
3190 usecase = node_to_item(node, struct audio_usecase, list);
3191 if (usecase->type == PCM_PLAYBACK) {
Steve Kondik3abbbc82014-11-29 14:14:43 -08003192 status = select_devices(adev, usecase->id);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303193 break;
3194 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003195 }
3196 }
3197 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003198 }
3199
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003200 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003201
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003202done:
3203 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003204 pthread_mutex_unlock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303205 ALOGV("%s: exit with code(%d)", __func__, status);
3206 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003207}
3208
3209static char* adev_get_parameters(const struct audio_hw_device *dev,
3210 const char *keys)
3211{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003212 struct audio_device *adev = (struct audio_device *)dev;
3213 struct str_parms *reply = str_parms_create();
3214 struct str_parms *query = str_parms_create_str(keys);
3215 char *str;
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303216 char value[256] = {0};
3217 int ret = 0;
3218
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003219 if (!query || !reply) {
3220 ALOGE("adev_get_parameters: failed to create query or reply");
3221 return NULL;
3222 }
3223
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303224 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
3225 sizeof(value));
3226 if (ret >=0) {
3227 int val = 1;
3228 pthread_mutex_lock(&adev->snd_card_status.lock);
3229 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3230 val = 0;
3231 pthread_mutex_unlock(&adev->snd_card_status.lock);
3232 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, val);
3233 goto exit;
3234 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003235
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003236 pthread_mutex_lock(&adev->lock);
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303237
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003238 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003239 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003240 platform_get_parameters(adev->platform, query, reply);
Naresh Tannirucef332d2014-06-04 18:17:56 +05303241 pthread_mutex_unlock(&adev->lock);
3242
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303243exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003244 str = str_parms_to_str(reply);
3245 str_parms_destroy(query);
3246 str_parms_destroy(reply);
3247
3248 ALOGV("%s: exit: returns - %s", __func__, str);
3249 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250}
3251
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303252static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003253{
3254 return 0;
3255}
3256
3257static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3258{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003259 int ret;
3260 struct audio_device *adev = (struct audio_device *)dev;
Eric Laurent321b96d2014-09-10 13:21:01 -05003261
3262 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3263
Haynes Mathew George5191a852013-09-11 14:19:36 -07003264 pthread_mutex_lock(&adev->lock);
3265 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003266 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003267 pthread_mutex_unlock(&adev->lock);
3268 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269}
3270
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303271static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3272 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003273{
3274 return -ENOSYS;
3275}
3276
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303277static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3278 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003279{
3280 return -ENOSYS;
3281}
3282
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303283static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3284 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003285{
3286 return -ENOSYS;
3287}
3288
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303289static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3290 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291{
3292 return -ENOSYS;
3293}
3294
3295static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3296{
3297 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 pthread_mutex_lock(&adev->lock);
3299 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003300 ALOGD("%s mode %d\n", __func__, mode);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303301 if (amplifier_set_mode(mode) != 0)
3302 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303 adev->mode = mode;
3304 }
3305 pthread_mutex_unlock(&adev->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003306
3307 audio_extn_extspk_set_mode(adev->extspk, mode);
3308
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 return 0;
3310}
3311
3312static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3313{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003314 int ret;
3315
3316 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003317 ALOGD("%s state %d\n", __func__, state);
Shreyas Nagasandra Chandrasekhar9781c6c2014-12-01 05:49:35 -08003318 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003319 pthread_mutex_unlock(&adev->lock);
3320
3321 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322}
3323
3324static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3325{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003326 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003327 return 0;
3328}
3329
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303330static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 const struct audio_config *config)
3332{
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303333 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003335 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3336 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003337}
3338
3339static int adev_open_input_stream(struct audio_hw_device *dev,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303340 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 audio_devices_t devices,
3342 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303343 struct audio_stream_in **stream_in,
3344 audio_input_flags_t flags __unused,
3345 const char *address __unused,
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003346 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347{
3348 struct audio_device *adev = (struct audio_device *)dev;
3349 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003350 int ret = 0, buffer_size, frame_size;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303351 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003352 bool is_low_latency = false;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003354 *stream_in = NULL;
3355 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3356 return -EINVAL;
3357
3358 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003359
3360 if (!in) {
3361 ALOGE("failed to allocate input stream");
3362 return -ENOMEM;
3363 }
3364
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303365 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003366 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3367 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003368
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003369 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 in->stream.common.get_sample_rate = in_get_sample_rate;
3372 in->stream.common.set_sample_rate = in_set_sample_rate;
3373 in->stream.common.get_buffer_size = in_get_buffer_size;
3374 in->stream.common.get_channels = in_get_channels;
3375 in->stream.common.get_format = in_get_format;
3376 in->stream.common.set_format = in_set_format;
3377 in->stream.common.standby = in_standby;
3378 in->stream.common.dump = in_dump;
3379 in->stream.common.set_parameters = in_set_parameters;
3380 in->stream.common.get_parameters = in_get_parameters;
3381 in->stream.common.add_audio_effect = in_add_audio_effect;
3382 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3383 in->stream.set_gain = in_set_gain;
3384 in->stream.read = in_read;
3385 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3386
3387 in->device = devices;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003388 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390 in->standby = 1;
3391 in->channel_mask = config->channel_mask;
3392
3393 /* Update config params with the requested sample rate and channels */
3394 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003395 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3396 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3397 is_low_latency = true;
3398#if LOW_LATENCY_CAPTURE_USE_CASE
3399 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3400#endif
3401 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003402 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003404 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303406 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkala3c0036d2014-12-17 16:45:10 +05303407 if (adev->mode != AUDIO_MODE_IN_CALL) {
3408 ret = -EINVAL;
3409 goto err_open;
Pavan Chikkala3ec42ef2014-11-21 20:57:48 +05303410 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303411 if (config->sample_rate == 0)
3412 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3413 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3414 config->sample_rate != 8000) {
3415 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3416 ret = -EINVAL;
3417 goto err_open;
3418 }
3419 if (config->format == AUDIO_FORMAT_DEFAULT)
3420 config->format = AUDIO_FORMAT_PCM_16_BIT;
3421 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3422 config->format = AUDIO_FORMAT_PCM_16_BIT;
3423 ret = -EINVAL;
3424 goto err_open;
3425 }
3426 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3427 in->config = pcm_config_afe_proxy_record;
3428 in->config.channels = channel_count;
3429 in->config.rate = config->sample_rate;
3430 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003431 if(audio_extn_ssr_get_enabled()) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303432 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003433 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3434 ret = -EINVAL;
3435 goto err_open;
3436 }
3437 } else {
Mingming Yindaf9c542014-09-16 17:41:33 -07003438 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003439 }
Mingming Yine62d7842013-10-25 16:26:03 -07003440 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08003441 audio_extn_compr_cap_format_supported(config->format) &&
3442 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303443 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003444 } else {
3445 in->config.channels = channel_count;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303446 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003447 buffer_size = get_input_buffer_size(config->sample_rate,
3448 config->format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003449 channel_count,
3450 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003451 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003452 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3453 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3454 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3455 (in->config.rate == 8000 || in->config.rate == 16000) &&
3456 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3457 voice_extn_compress_voip_open_input_stream(in);
3458 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003459 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460
3461 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003462 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003463 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003464
3465err_open:
3466 free(in);
3467 *stream_in = NULL;
3468 return ret;
3469}
3470
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303471static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003472 struct audio_stream_in *stream)
3473{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003474 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003475 struct stream_in *in = (struct stream_in *)stream;
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303476 struct audio_device *adev = in->dev;
3477
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303478 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003479
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003480 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303481 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003482 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303483 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003484 if (ret != 0)
3485 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3486 __func__, ret);
3487 } else
3488 in_standby(&stream->common);
3489
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303490 if (audio_extn_ssr_get_enabled() &&
3491 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003492 audio_extn_ssr_deinit();
3493 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 free(stream);
3495
Mingming Yine62d7842013-10-25 16:26:03 -07003496 if(audio_extn_compr_cap_enabled() &&
3497 audio_extn_compr_cap_format_supported(in->config.format))
3498 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003499 return;
3500}
3501
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303502static int adev_dump(const audio_hw_device_t *device __unused,
3503 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504{
3505 return 0;
3506}
3507
Steve Kondik3abbbc82014-11-29 14:14:43 -08003508/* verifies input and output devices and their capabilities.
3509 *
3510 * This verification is required when enabling extended bit-depth or
3511 * sampling rates, as not all qcom products support it.
3512 *
3513 * Suitable for calling only on initialization such as adev_open().
3514 * It fills the audio_device use_case_table[] array.
3515 *
3516 * Has a side-effect that it needs to configure audio routing / devices
3517 * in order to power up the devices and read the device parameters.
3518 * It does not acquire any hw device lock. Should restore the devices
3519 * back to "normal state" upon completion.
3520 */
3521static int adev_verify_devices(struct audio_device *adev)
3522{
3523 /* enumeration is a bit difficult because one really wants to pull
3524 * the use_case, device id, etc from the hidden pcm_device_table[].
3525 * In this case there are the following use cases and device ids.
3526 *
3527 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3528 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3529 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3530 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3531 * [USECASE_AUDIO_RECORD] = {0, 0},
3532 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3533 * [USECASE_VOICE_CALL] = {2, 2},
3534 *
3535 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3536 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3537 */
3538
3539 /* should be the usecases enabled in adev_open_input_stream() */
3540 static const int test_in_usecases[] = {
3541 USECASE_AUDIO_RECORD,
3542 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3543 };
3544 /* should be the usecases enabled in adev_open_output_stream()*/
3545 static const int test_out_usecases[] = {
3546 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3547 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3548 };
3549 static const usecase_type_t usecase_type_by_dir[] = {
3550 PCM_PLAYBACK,
3551 PCM_CAPTURE,
3552 };
3553 static const unsigned flags_by_dir[] = {
3554 PCM_OUT,
3555 PCM_IN,
3556 };
3557
3558 size_t i;
3559 unsigned dir;
3560 const unsigned card_id = adev->snd_card;
3561 char info[512]; /* for possible debug info */
3562
3563 for (dir = 0; dir < 2; ++dir) {
3564 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3565 const unsigned flags_dir = flags_by_dir[dir];
3566 const size_t testsize =
3567 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3568 const int *testcases =
3569 dir ? test_in_usecases : test_out_usecases;
3570 const audio_devices_t audio_device =
3571 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3572
3573 for (i = 0; i < testsize; ++i) {
3574 const audio_usecase_t audio_usecase = testcases[i];
3575 int device_id;
3576 snd_device_t snd_device;
3577 struct pcm_params **pparams;
3578 struct stream_out out;
3579 struct stream_in in;
3580 struct audio_usecase uc_info;
3581 int retval;
3582
3583 pparams = &adev->use_case_table[audio_usecase];
3584 pcm_params_free(*pparams); /* can accept null input */
3585 *pparams = NULL;
3586
3587 /* find the device ID for the use case (signed, for error) */
3588 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3589 if (device_id < 0)
3590 continue;
3591
3592 /* prepare structures for device probing */
3593 memset(&uc_info, 0, sizeof(uc_info));
3594 uc_info.id = audio_usecase;
3595 uc_info.type = usecase_type;
3596 if (dir) {
3597 adev->active_input = &in;
3598 memset(&in, 0, sizeof(in));
3599 in.device = audio_device;
3600 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3601 uc_info.stream.in = &in;
3602 } else {
3603 adev->active_input = NULL;
3604 }
3605 memset(&out, 0, sizeof(out));
3606 out.devices = audio_device; /* only field needed in select_devices */
3607 uc_info.stream.out = &out;
3608 uc_info.devices = audio_device;
3609 uc_info.in_snd_device = SND_DEVICE_NONE;
3610 uc_info.out_snd_device = SND_DEVICE_NONE;
3611 list_add_tail(&adev->usecase_list, &uc_info.list);
3612
3613 /* select device - similar to start_(in/out)put_stream() */
3614 retval = select_devices(adev, audio_usecase);
3615 if (retval >= 0) {
3616 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3617#if LOG_NDEBUG == 0
3618 if (*pparams) {
3619 ALOGV("%s: (%s) card %d device %d", __func__,
3620 dir ? "input" : "output", card_id, device_id);
3621 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
3622 ALOGV(info); /* print parameters */
3623 } else {
3624 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3625 }
3626#endif
3627 }
3628
3629 /* deselect device - similar to stop_(in/out)put_stream() */
3630 /* 1. Get and set stream specific mixer controls */
3631 retval = disable_audio_route(adev, &uc_info);
3632 /* 2. Disable the rx device */
3633 retval = disable_snd_device(adev,
3634 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
3635 list_remove(&uc_info.list);
3636 }
3637 }
3638 adev->active_input = NULL; /* restore adev state */
3639 return 0;
3640}
3641
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003642static int adev_close(hw_device_t *device)
3643{
Steve Kondik3abbbc82014-11-29 14:14:43 -08003644 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003646
3647 if (!adev)
3648 return 0;
3649
3650 pthread_mutex_lock(&adev_init_lock);
3651
3652 if ((--audio_device_ref_count) == 0) {
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303653 if (amplifier_close() != 0)
3654 ALOGE("Amplifier close failed");
Kiran Kandide144c82013-11-20 15:58:32 -08003655 audio_extn_listen_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07003656 audio_route_free(adev->audio_route);
3657 free(adev->snd_dev_ref_cnt);
3658 platform_deinit(adev->platform);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003659 audio_extn_extspk_deinit(adev->extspk);
Steve Kondik3abbbc82014-11-29 14:14:43 -08003660 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3661 pcm_params_free(adev->use_case_table[i]);
3662 }
Kiran Kandi910e1862013-10-29 13:29:42 -07003663 free(device);
3664 adev = NULL;
3665 }
3666 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 return 0;
3668}
3669
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003670/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3671 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3672 * just that it _might_ work.
3673 */
3674static int period_size_is_plausible_for_low_latency(int period_size)
3675{
3676 switch (period_size) {
3677 case 160:
3678 case 240:
3679 case 320:
3680 case 480:
3681 return 1;
3682 default:
3683 return 0;
3684 }
3685}
3686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687static int adev_open(const hw_module_t *module, const char *name,
3688 hw_device_t **device)
3689{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003690 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003691
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003692 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3694
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003695 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003696 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003697 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003698 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003699 ALOGD("%s: returning existing instance of adev", __func__);
3700 ALOGD("%s: exit", __func__);
3701 pthread_mutex_unlock(&adev_init_lock);
3702 return 0;
3703 }
3704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705 adev = calloc(1, sizeof(struct audio_device));
3706
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003707 if (!adev) {
3708 pthread_mutex_unlock(&adev_init_lock);
3709 return -ENOMEM;
3710 }
3711
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003712 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3713
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003714 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3715 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3716 adev->device.common.module = (struct hw_module_t *)module;
3717 adev->device.common.close = adev_close;
3718
3719 adev->device.init_check = adev_init_check;
3720 adev->device.set_voice_volume = adev_set_voice_volume;
3721 adev->device.set_master_volume = adev_set_master_volume;
3722 adev->device.get_master_volume = adev_get_master_volume;
3723 adev->device.set_master_mute = adev_set_master_mute;
3724 adev->device.get_master_mute = adev_get_master_mute;
3725 adev->device.set_mode = adev_set_mode;
3726 adev->device.set_mic_mute = adev_set_mic_mute;
3727 adev->device.get_mic_mute = adev_get_mic_mute;
3728 adev->device.set_parameters = adev_set_parameters;
3729 adev->device.get_parameters = adev_get_parameters;
3730 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3731 adev->device.open_output_stream = adev_open_output_stream;
3732 adev->device.close_output_stream = adev_close_output_stream;
3733 adev->device.open_input_stream = adev_open_input_stream;
3734 adev->device.close_input_stream = adev_close_input_stream;
3735 adev->device.dump = adev_dump;
3736
3737 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003738 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003739 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003740 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003741 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003742 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003743 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003744 /* adev->cur_hdmi_channels = 0; by calloc() */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08003745 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3746 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003747 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003748 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003749 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly9b7e96b2014-02-14 14:45:49 -08003750 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003751 adev->offload_usecases_state = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003752
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303753 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3754 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
3755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003757 adev->platform = platform_init(adev);
3758 if (!adev->platform) {
3759 free(adev->snd_dev_ref_cnt);
3760 free(adev);
3761 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3762 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003763 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003764 return -EINVAL;
3765 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003766
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303767 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
Eric Laurentda46bfb2014-08-25 22:39:29 -05003768 adev->extspk = audio_extn_extspk_init(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303769
Eric Laurentc4aef752013-09-12 17:45:53 -07003770 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3771 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3772 if (adev->visualizer_lib == NULL) {
3773 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3774 } else {
3775 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3776 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003777 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003778 "visualizer_hal_start_output");
3779 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003780 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003781 "visualizer_hal_stop_output");
3782 }
3783 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003784 audio_extn_listen_init(adev, adev->snd_card);
Eric Laurentc4aef752013-09-12 17:45:53 -07003785
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003786 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3787 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3788 if (adev->offload_effects_lib == NULL) {
3789 ALOGE("%s: DLOPEN failed for %s", __func__,
3790 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3791 } else {
3792 ALOGV("%s: DLOPEN successful for %s", __func__,
3793 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3794 adev->offload_effects_start_output =
3795 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3796 "offload_effects_bundle_hal_start_output");
3797 adev->offload_effects_stop_output =
3798 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3799 "offload_effects_bundle_hal_stop_output");
3800 }
3801 }
3802
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803 *device = &adev->device.common;
Steve Kondik3abbbc82014-11-29 14:14:43 -08003804 if (k_enable_extended_precision)
3805 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303807 if (amplifier_open() != 0)
3808 ALOGE("Amplifier initialization failed");
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303809
Kiran Kandi910e1862013-10-29 13:29:42 -07003810 audio_device_ref_count++;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003811
3812 char value[PROPERTY_VALUE_MAX];
3813 int trial;
3814 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3815 trial = atoi(value);
3816 if (period_size_is_plausible_for_low_latency(trial)) {
3817 pcm_config_low_latency.period_size = trial;
3818 pcm_config_low_latency.start_threshold = trial / 4;
3819 pcm_config_low_latency.avail_min = trial / 4;
3820 configured_low_latency_capture_period_size = trial;
3821 }
3822 }
3823 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3824 trial = atoi(value);
3825 if (period_size_is_plausible_for_low_latency(trial)) {
3826 configured_low_latency_capture_period_size = trial;
3827 }
3828 }
3829
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003830 pthread_mutex_unlock(&adev_init_lock);
3831
Eric Laurent994a6932013-07-17 11:51:42 -07003832 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003833 return 0;
3834}
3835
3836static struct hw_module_methods_t hal_module_methods = {
3837 .open = adev_open,
3838};
3839
3840struct audio_module HAL_MODULE_INFO_SYM = {
3841 .common = {
3842 .tag = HARDWARE_MODULE_TAG,
3843 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3844 .hal_api_version = HARDWARE_HAL_API_VERSION,
3845 .id = AUDIO_HARDWARE_MODULE_ID,
3846 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003847 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003848 .methods = &hal_module_methods,
3849 },
3850};