blob: fa65ec3317a13fcb07ed0560b3605cf4d39ad829 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20#define LOG_TAG "audio_hw_primary"
Steve Kondik5a447012014-12-02 16:04:20 -080021//#define LOG_NDEBUG 0
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070022/*#define VERY_VERY_VERBOSE_LOGGING*/
23#ifdef VERY_VERY_VERBOSE_LOGGING
24#define ALOGVV ALOGV
25#else
26#define ALOGVV(a...) do { } while(0)
27#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080028#include <errno.h>
29#include <pthread.h>
30#include <stdint.h>
31#include <sys/time.h>
32#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080033#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070034#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070035#include <sys/resource.h>
36#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080037
38#include <cutils/log.h>
39#include <cutils/str_parms.h>
40#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041#include <cutils/atomic.h>
42#include <cutils/sched_policy.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080043
Eric Laurentb23d5282013-05-14 15:27:20 -070044#include <hardware/audio_effect.h>
Steve Kondik3abbbc82014-11-29 14:14:43 -080045#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070046#include <system/thread_defs.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070047#include <audio_effects/effect_aec.h>
48#include <audio_effects/effect_ns.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080049#include "audio_hw.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070050#include "platform_api.h"
51#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070052#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080053#include "voice_extn.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080054
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include "sound/compress_params.h"
ApurupaPattapu0c566872014-01-10 14:46:02 -080056#include "sound/asound.h"
57
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070058#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
59/* ToDo: Check and update a proper value in msec */
Alexy Joseph62babb92015-03-03 19:01:03 -080060#define COMPRESS_OFFLOAD_PLAYBACK_LATENCY 50
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070061#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
62
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +053063#define PROXY_OPEN_RETRY_COUNT 100
64#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapu0c566872014-01-10 14:46:02 -080065
Steve Kondikb045f472014-11-12 23:24:07 -080066#ifdef LOW_LATENCY_PRIMARY
67#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_LOW_LATENCY
68#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080069#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Steve Kondikb045f472014-11-12 23:24:07 -080070#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080071
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -070072static unsigned int configured_low_latency_capture_period_size =
73 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
74
Steve Kondik3abbbc82014-11-29 14:14:43 -080075/* This constant enables extended precision handling.
Steve Kondik3abbbc82014-11-29 14:14:43 -080076 */
77static const bool k_enable_extended_precision = true;
78
Eric Laurentb23d5282013-05-14 15:27:20 -070079struct pcm_config pcm_config_deep_buffer = {
80 .channels = 2,
81 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
82 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
83 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
84 .format = PCM_FORMAT_S16_LE,
85 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
86 .stop_threshold = INT_MAX,
87 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
88};
89
90struct pcm_config pcm_config_low_latency = {
91 .channels = 2,
92 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
93 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
94 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
95 .format = PCM_FORMAT_S16_LE,
96 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
97 .stop_threshold = INT_MAX,
98 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
99};
100
101struct pcm_config pcm_config_hdmi_multi = {
102 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
103 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
104 .period_size = HDMI_MULTI_PERIOD_SIZE,
105 .period_count = HDMI_MULTI_PERIOD_COUNT,
106 .format = PCM_FORMAT_S16_LE,
107 .start_threshold = 0,
108 .stop_threshold = INT_MAX,
109 .avail_min = 0,
110};
111
112struct pcm_config pcm_config_audio_capture = {
113 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700114 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
115 .format = PCM_FORMAT_S16_LE,
116};
117
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530118#define AFE_PROXY_CHANNEL_COUNT 2
119#define AFE_PROXY_SAMPLING_RATE 48000
120
121#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
122#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
123
124struct pcm_config pcm_config_afe_proxy_playback = {
125 .channels = AFE_PROXY_CHANNEL_COUNT,
126 .rate = AFE_PROXY_SAMPLING_RATE,
127 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
128 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
129 .format = PCM_FORMAT_S16_LE,
130 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
131 .stop_threshold = INT_MAX,
132 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
133};
134
135#define AFE_PROXY_RECORD_PERIOD_SIZE 768
136#define AFE_PROXY_RECORD_PERIOD_COUNT 4
137
138struct pcm_config pcm_config_afe_proxy_record = {
139 .channels = AFE_PROXY_CHANNEL_COUNT,
140 .rate = AFE_PROXY_SAMPLING_RATE,
141 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
142 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
143 .format = PCM_FORMAT_S16_LE,
144 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
145 .stop_threshold = INT_MAX,
146 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
147};
148
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800149const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700150 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
151 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
152 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700153 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700154#ifdef MULTIPLE_OFFLOAD_ENABLED
155 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
156 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
157 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
158 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
159 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
160 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
161 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
162 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
163#endif
Eric Laurentb23d5282013-05-14 15:27:20 -0700164 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700165 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700166 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700167 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700168 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800169 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800170 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700171 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yinee733602014-04-03 17:47:22 -0700172
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700173 [USECASE_VOICE2_CALL] = "voice2-call",
174 [USECASE_VOLTE_CALL] = "volte-call",
175 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat111aeb32014-02-12 17:58:59 -0800176 [USECASE_VOWLAN_CALL] = "vowlan-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800177 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700178 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
179 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
180 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800181 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
182 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
183 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
184
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700185 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
186 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700187 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
188 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530189
190 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
191 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700192};
193
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700194static const audio_usecase_t offload_usecases[] = {
195 USECASE_AUDIO_PLAYBACK_OFFLOAD,
196#ifdef MULTIPLE_OFFLOAD_ENABLED
197 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
198 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
Steve Kondikac72feb2014-07-20 23:15:34 -0700199#ifndef PLATFORM_MSM8974
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700200 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
201 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
202 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
203 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
Steve Kondikac72feb2014-07-20 23:15:34 -0700204#endif
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700205 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
Steve Kondikac72feb2014-07-20 23:15:34 -0700206#ifndef PLATFORM_MSM8974
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700207 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
208#endif
Steve Kondikac72feb2014-07-20 23:15:34 -0700209#endif
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700210};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800211
212#define STRING_TO_ENUM(string) { #string, string }
213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800214struct string_to_enum {
215 const char *name;
216 uint32_t value;
217};
218
219static const struct string_to_enum out_channels_name_to_enum_table[] = {
220 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
221 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
222 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
223};
224
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700225static struct audio_device *adev = NULL;
226static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700227static unsigned int audio_device_ref_count;
228
Haynes Mathew George5191a852013-09-11 14:19:36 -0700229static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800230
Ethan Chen79c356c2015-06-07 12:26:14 -0700231static amplifier_device_t * get_amplifier_device(void)
232{
Dan Pasanen46f76f52015-08-10 19:55:39 -0500233 if (adev)
234 return adev->amp;
235
236 return NULL;
237}
238
239static int amplifier_open(void)
240{
Ethan Chen79c356c2015-06-07 12:26:14 -0700241 int rc;
242 amplifier_module_t *module;
243
Ethan Chen79c356c2015-06-07 12:26:14 -0700244 rc = hw_get_module(AMPLIFIER_HARDWARE_MODULE_ID,
245 (const hw_module_t **) &module);
246 if (rc) {
247 ALOGV("%s: Failed to obtain reference to amplifier module: %s\n",
248 __func__, strerror(-rc));
Dan Pasanen46f76f52015-08-10 19:55:39 -0500249 return -ENODEV;
Ethan Chen79c356c2015-06-07 12:26:14 -0700250 }
251
252 rc = amplifier_device_open((const hw_module_t *) module, &adev->amp);
253 if (rc) {
254 ALOGV("%s: Failed to open amplifier hardware device: %s\n",
255 __func__, strerror(-rc));
Ethan Chen79c356c2015-06-07 12:26:14 -0700256 return -ENODEV;
257 }
258
259 return 0;
260}
261
262static int amplifier_set_input_devices(uint32_t devices)
263{
264 amplifier_device_t *amp = get_amplifier_device();
265 if (amp && amp->set_input_devices)
266 return amp->set_input_devices(amp, devices);
267
268 return 0;
269}
270
271static int amplifier_set_output_devices(uint32_t devices)
272{
273 amplifier_device_t *amp = get_amplifier_device();
274 if (amp && amp->set_output_devices)
275 return amp->set_output_devices(amp, devices);
276
277 return 0;
278}
279
Ethan Chen6720ae62015-07-03 21:35:30 -0700280static int amplifier_enable_devices(uint32_t devices, bool enable)
281{
282 amplifier_device_t *amp = get_amplifier_device();
283 bool is_output = devices > SND_DEVICE_OUT_BEGIN &&
284 devices < SND_DEVICE_OUT_END;
285
286 if (amp && amp->enable_output_devices && is_output)
287 return amp->enable_output_devices(amp, devices, enable);
288
289 if (amp && amp->enable_input_devices && !is_output)
290 return amp->enable_input_devices(amp, devices, enable);
291
292 return 0;
293}
294
Ethan Chen79c356c2015-06-07 12:26:14 -0700295static int amplifier_set_mode(audio_mode_t mode)
296{
297 amplifier_device_t *amp = get_amplifier_device();
298 if (amp && amp->set_mode)
299 return amp->set_mode(amp, mode);
300
301 return 0;
302}
303
304static int amplifier_output_stream_start(struct audio_stream_out *stream,
305 bool offload)
306{
307 amplifier_device_t *amp = get_amplifier_device();
308 if (amp && amp->output_stream_start)
309 return amp->output_stream_start(amp, stream, offload);
310
311 return 0;
312}
313
314static int amplifier_input_stream_start(struct audio_stream_in *stream)
315{
316 amplifier_device_t *amp = get_amplifier_device();
317 if (amp && amp->input_stream_start)
318 return amp->input_stream_start(amp, stream);
319
320 return 0;
321}
322
323static int amplifier_output_stream_standby(struct audio_stream_out *stream)
324{
325 amplifier_device_t *amp = get_amplifier_device();
326 if (amp && amp->output_stream_standby)
327 return amp->output_stream_standby(amp, stream);
328
329 return 0;
330}
331
332static int amplifier_input_stream_standby(struct audio_stream_in *stream)
333{
334 amplifier_device_t *amp = get_amplifier_device();
335 if (amp && amp->input_stream_standby)
336 return amp->input_stream_standby(amp, stream);
337
338 return 0;
339}
340
341static int amplifier_close(void)
342{
343 amplifier_device_t *amp = get_amplifier_device();
344 if (amp)
345 amplifier_device_close(amp);
346
347 return 0;
348}
349
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800350static int check_and_set_gapless_mode(struct audio_device *adev) {
351
352
353 char value[PROPERTY_VALUE_MAX] = {0};
354 bool gapless_enabled = false;
355 const char *mixer_ctl_name = "Compress Gapless Playback";
356 struct mixer_ctl *ctl;
357
358 ALOGV("%s:", __func__);
359 property_get("audio.offload.gapless.enabled", value, NULL);
360 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
361
362 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
363 if (!ctl) {
364 ALOGE("%s: Could not get ctl for mixer cmd - %s",
365 __func__, mixer_ctl_name);
366 return -EINVAL;
367 }
368
369 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
370 ALOGE("%s: Could not set gapless mode %d",
371 __func__, gapless_enabled);
372 return -EINVAL;
373 }
374 return 0;
375}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700376
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700377static bool is_supported_format(audio_format_t format)
378{
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800379 switch (format) {
Steve Kondik3abbbc82014-11-29 14:14:43 -0800380 case AUDIO_FORMAT_MP3:
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800381 case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
382 case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700383#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik3abbbc82014-11-29 14:14:43 -0800384 case AUDIO_FORMAT_FLAC:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700385#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -0800386#ifdef WMA_OFFLOAD_ENABLED
387 case AUDIO_FORMAT_WMA:
388 case AUDIO_FORMAT_WMA_PRO:
389#endif
390#ifdef MP2_OFFLOAD_ENABLED
391 case AUDIO_FORMAT_MP2:
392#endif
393 case AUDIO_FORMAT_AAC_LC:
394 case AUDIO_FORMAT_AAC_HE_V1:
395 case AUDIO_FORMAT_AAC_HE_V2:
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530396 return true;
Steve Kondik3abbbc82014-11-29 14:14:43 -0800397
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800398 default:
399 return false;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530400 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700401 return false;
402}
403
404static int get_snd_codec_id(audio_format_t format)
405{
406 int id = 0;
407
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530408 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700409 case AUDIO_FORMAT_MP3:
410 id = SND_AUDIOCODEC_MP3;
411 break;
412 case AUDIO_FORMAT_AAC:
413 id = SND_AUDIOCODEC_AAC;
414 break;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530415 case AUDIO_FORMAT_PCM_OFFLOAD:
ApurupaPattapu0c566872014-01-10 14:46:02 -0800416 id = SND_AUDIOCODEC_PCM;
417 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700418#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800419 case AUDIO_FORMAT_FLAC:
420 id = SND_AUDIOCODEC_FLAC;
421 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700422#endif
Ethan Chenc856d972014-07-25 14:57:15 -0700423#ifdef WMA_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700424 case AUDIO_FORMAT_WMA:
425 id = SND_AUDIOCODEC_WMA;
426 break;
427 case AUDIO_FORMAT_WMA_PRO:
428 id = SND_AUDIOCODEC_WMA_PRO;
429 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700430#endif
431#ifdef MP2_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700432 case AUDIO_FORMAT_MP2:
433 id = SND_AUDIOCODEC_MP2;
434 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700435#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700436 default:
Mingming Yin90310102013-11-13 16:57:00 -0800437 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700438 }
439
440 return id;
441}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800442
Avinash Vaish8005dc82014-07-24 15:36:33 +0530443static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
444 struct audio_usecase *uc_info)
445{
446 struct listnode *node;
447 struct audio_usecase *usecase;
448
449 if (uc_info == NULL)
450 return -EINVAL;
451
452 /* Re-route all voice usecases on the shared backend other than the
453 specified usecase to new snd devices */
454 list_for_each(node, &adev->usecase_list) {
455 usecase = node_to_item(node, struct audio_usecase, list);
456 if ((usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) &&
457 (usecase != uc_info))
458 enable_audio_route(adev, usecase);
459 }
460 return 0;
461}
462
Venkata Narendra Kumar Guttac9e9e2c2014-07-09 16:29:28 +0530463int get_snd_card_state(struct audio_device *adev)
Naresh Tannirucef332d2014-06-04 18:17:56 +0530464{
465 int snd_scard_state;
466
467 if (!adev)
468 return SND_CARD_STATE_OFFLINE;
469
470 pthread_mutex_lock(&adev->snd_card_status.lock);
471 snd_scard_state = adev->snd_card_status.state;
472 pthread_mutex_unlock(&adev->snd_card_status.lock);
473
474 return snd_scard_state;
475}
476
477static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
478{
479 if (!adev)
480 return -ENOSYS;
481
482 pthread_mutex_lock(&adev->snd_card_status.lock);
483 adev->snd_card_status.state = snd_scard_state;
484 pthread_mutex_unlock(&adev->snd_card_status.lock);
485
486 return 0;
487}
488
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -0700489int pcm_ioctl(struct pcm *pcm, int request, ...)
490{
491 va_list ap;
492 void * arg;
493 int pcm_fd = *(int*)pcm;
494
495 va_start(ap, request);
496 arg = va_arg(ap, void *);
497 va_end(ap);
498
499 return ioctl(pcm_fd, request, arg);
500}
501
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700502int enable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700503 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800504{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700505 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700506 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800507
508 if (usecase == NULL)
509 return -EINVAL;
510
511 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
512
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800513 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700514 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800515 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700516 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800517
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -0800518#ifdef DS1_DOLBY_DAP_ENABLED
519 audio_extn_dolby_set_dmid(adev);
520 audio_extn_dolby_set_endpoint(adev);
521#endif
Steve Kondik0d268002015-10-16 01:57:18 -0700522 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800523 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700524 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700525 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
526 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800527 ALOGV("%s: exit", __func__);
528 return 0;
529}
530
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700531int disable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700532 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800533{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700534 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700535 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800536
537 if (usecase == NULL)
538 return -EINVAL;
539
540 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700541 if (usecase->type == PCM_CAPTURE)
542 snd_device = usecase->in_snd_device;
543 else
544 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800545 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700546 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700547 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
548 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Steve Kondik0d268002015-10-16 01:57:18 -0700549 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800550 ALOGV("%s: exit", __func__);
551 return 0;
552}
553
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700554int enable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700555 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800556{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700557 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
558
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800559 if (snd_device < SND_DEVICE_MIN ||
560 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800561 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800562 return -EINVAL;
563 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700564
565 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700566
567 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
568 ALOGE("%s: Invalid sound device returned", __func__);
569 return -EINVAL;
570 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700571 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700572 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700573 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700574 return 0;
575 }
576
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700577 /* start usb playback thread */
578 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
579 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
580 audio_extn_usb_start_playback(adev);
581
582 /* start usb capture thread */
583 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
584 audio_extn_usb_start_capture(adev);
585
Tony Layher692f19a2015-01-03 13:16:45 -0500586 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
587 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700588 audio_extn_spkr_prot_is_enabled()) {
589 if (audio_extn_spkr_prot_start_processing(snd_device)) {
590 ALOGE("%s: spkr_start_processing failed", __func__);
591 return -EINVAL;
592 }
593 } else {
594 ALOGV("%s: snd_device(%d: %s)", __func__,
Steve Kondik0d268002015-10-16 01:57:18 -0700595 snd_device, device_name);
596 /* due to the possibility of calibration overwrite between listen
597 and audio, notify listen hal before audio calibration is sent */
598 audio_extn_listen_update_device_status(snd_device,
599 LISTEN_EVENT_SND_DEVICE_BUSY);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700600 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
601 adev->snd_dev_ref_cnt[snd_device]--;
Steve Kondik0d268002015-10-16 01:57:18 -0700602 audio_extn_listen_update_device_status(snd_device,
603 LISTEN_EVENT_SND_DEVICE_FREE);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700604 return -EINVAL;
605 }
Kiran Kandide144c82013-11-20 15:58:32 -0800606
Ethan Chen6720ae62015-07-03 21:35:30 -0700607 amplifier_enable_devices(snd_device, true);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700608 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800609 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800610 return 0;
611}
612
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700613int disable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700614 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800615{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700616 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
617
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800618 if (snd_device < SND_DEVICE_MIN ||
619 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800620 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800621 return -EINVAL;
622 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700623 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
624 ALOGE("%s: device ref cnt is already 0", __func__);
625 return -EINVAL;
626 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700627
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700628 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700629
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700630 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
631 ALOGE("%s: Invalid sound device returned", __func__);
632 return -EINVAL;
633 }
634
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700635 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700636 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700637 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800638 /* exit usb play back thread */
639 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
640 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
641 audio_extn_usb_stop_playback();
642
643 /* exit usb capture thread */
644 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Rajshekar Eashwarappa4dfa0752014-10-02 20:18:20 +0530645 audio_extn_usb_stop_capture();
Tony Layher692f19a2015-01-03 13:16:45 -0500646
647 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
648 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700649 audio_extn_spkr_prot_is_enabled()) {
650 audio_extn_spkr_prot_stop_processing();
Ethan Chen6720ae62015-07-03 21:35:30 -0700651 } else {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700652 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ethan Chen6720ae62015-07-03 21:35:30 -0700653 amplifier_enable_devices(snd_device, false);
654 }
Kiran Kandide144c82013-11-20 15:58:32 -0800655
Steve Kondik0d268002015-10-16 01:57:18 -0700656 audio_extn_listen_update_device_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800657 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700658 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700659
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800660 return 0;
661}
662
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700663static void check_usecases_codec_backend(struct audio_device *adev,
664 struct audio_usecase *uc_info,
665 snd_device_t snd_device)
666{
667 struct listnode *node;
668 struct audio_usecase *usecase;
669 bool switch_device[AUDIO_USECASE_MAX];
670 int i, num_uc_to_switch = 0;
671
672 /*
673 * This function is to make sure that all the usecases that are active on
674 * the hardware codec backend are always routed to any one device that is
675 * handled by the hardware codec.
676 * For example, if low-latency and deep-buffer usecases are currently active
677 * on speaker and out_set_parameters(headset) is received on low-latency
678 * output, then we have to make sure deep-buffer is also switched to headset,
679 * because of the limitation that both the devices cannot be enabled
680 * at the same time as they share the same backend.
681 */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800682 /*
683 * This call is to check if we need to force routing for a particular stream
684 * If there is a backend configuration change for the device when a
685 * new stream starts, then ADM needs to be closed and re-opened with the new
686 * configuraion. This call check if we need to re-route all the streams
687 * associated with the backend. Touch tone + 24 bit playback.
688 */
689 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
690
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700691 /* Disable all the usecases on the shared backend other than the
692 specified usecase */
693 for (i = 0; i < AUDIO_USECASE_MAX; i++)
694 switch_device[i] = false;
695
696 list_for_each(node, &adev->usecase_list) {
697 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800698 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700699 usecase != uc_info &&
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800700 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700701 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
702 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
703 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700704 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700705 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700706 switch_device[usecase->id] = true;
707 num_uc_to_switch++;
708 }
709 }
710
711 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700712 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700713
714 list_for_each(node, &adev->usecase_list) {
715 usecase = node_to_item(node, struct audio_usecase, list);
716 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700717 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700718 }
719 }
720
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700721 list_for_each(node, &adev->usecase_list) {
722 usecase = node_to_item(node, struct audio_usecase, list);
723 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700724 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700725 }
726 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700727
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700728 /* Re-route all the usecases on the shared backend other than the
729 specified usecase to new snd devices */
730 list_for_each(node, &adev->usecase_list) {
731 usecase = node_to_item(node, struct audio_usecase, list);
732 /* Update the out_snd_device only before enabling the audio route */
733 if (switch_device[usecase->id] ) {
734 usecase->out_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530735 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
736 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700737 }
738 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700739 }
740}
741
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700742static void check_and_route_capture_usecases(struct audio_device *adev,
743 struct audio_usecase *uc_info,
744 snd_device_t snd_device)
745{
746 struct listnode *node;
747 struct audio_usecase *usecase;
748 bool switch_device[AUDIO_USECASE_MAX];
749 int i, num_uc_to_switch = 0;
750
751 /*
752 * This function is to make sure that all the active capture usecases
753 * are always routed to the same input sound device.
754 * For example, if audio-record and voice-call usecases are currently
755 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
756 * is received for voice call then we have to make sure that audio-record
757 * usecase is also switched to earpiece i.e. voice-dmic-ef,
758 * because of the limitation that two devices cannot be enabled
759 * at the same time if they share the same backend.
760 */
761 for (i = 0; i < AUDIO_USECASE_MAX; i++)
762 switch_device[i] = false;
763
764 list_for_each(node, &adev->usecase_list) {
765 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800766 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700767 usecase != uc_info &&
Avinash Vaish44014792015-03-27 14:46:04 +0530768 usecase->in_snd_device != snd_device &&
769 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700770 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
771 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700772 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700773 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774 switch_device[usecase->id] = true;
775 num_uc_to_switch++;
776 }
777 }
778
779 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700780 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700781
782 list_for_each(node, &adev->usecase_list) {
783 usecase = node_to_item(node, struct audio_usecase, list);
784 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700785 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800786 }
787 }
788
789 list_for_each(node, &adev->usecase_list) {
790 usecase = node_to_item(node, struct audio_usecase, list);
791 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700792 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700793 }
794 }
795
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700796 /* Re-route all the usecases on the shared backend other than the
797 specified usecase to new snd devices */
798 list_for_each(node, &adev->usecase_list) {
799 usecase = node_to_item(node, struct audio_usecase, list);
800 /* Update the in_snd_device only before enabling the audio route */
801 if (switch_device[usecase->id] ) {
802 usecase->in_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530803 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
804 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700805 }
806 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700807 }
808}
809
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800810/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700811static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800812{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700813 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700814 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800815
816 switch (channels) {
817 /*
818 * Do not handle stereo output in Multi-channel cases
819 * Stereo case is handled in normal playback path
820 */
821 case 6:
822 ALOGV("%s: HDMI supports 5.1", __func__);
823 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
824 break;
825 case 8:
826 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
827 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
828 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
829 break;
830 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700831 ALOGE("HDMI does not support multi channel playback");
832 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800833 break;
834 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700835 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800836}
837
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700838static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
839{
840 struct audio_usecase *usecase;
841 struct listnode *node;
842
843 list_for_each(node, &adev->usecase_list) {
844 usecase = node_to_item(node, struct audio_usecase, list);
845 if (usecase->type == VOICE_CALL) {
846 ALOGV("%s: usecase id %d", __func__, usecase->id);
847 return usecase->id;
848 }
849 }
850 return USECASE_INVALID;
851}
852
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700853struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700854 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700855{
856 struct audio_usecase *usecase;
857 struct listnode *node;
858
859 list_for_each(node, &adev->usecase_list) {
860 usecase = node_to_item(node, struct audio_usecase, list);
861 if (usecase->id == uc_id)
862 return usecase;
863 }
864 return NULL;
865}
866
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700867int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800868{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800869 snd_device_t out_snd_device = SND_DEVICE_NONE;
870 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700871 struct audio_usecase *usecase = NULL;
872 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800873 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800874 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800875 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800876 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700877 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800878
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879 usecase = get_usecase_from_list(adev, uc_id);
880 if (usecase == NULL) {
881 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
882 return -EINVAL;
883 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800884
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800885 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800886 (usecase->type == VOIP_CALL) ||
887 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700888 out_snd_device = platform_get_output_snd_device(adev->platform,
889 usecase->stream.out->devices);
890 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700891 usecase->devices = usecase->stream.out->devices;
892 } else {
893 /*
894 * If the voice call is active, use the sound devices of voice call usecase
895 * so that it would not result any device switch. All the usecases will
896 * be switched to new device when select_devices() is called for voice call
897 * usecase. This is to avoid switching devices for voice call when
898 * check_usecases_codec_backend() is called below.
899 */
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -0700900 if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700901 vc_usecase = get_usecase_from_list(adev,
902 get_voice_usecase_id_from_list(adev));
Mingming Yin6c23f382014-08-14 00:00:51 -0700903 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
904 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700905 in_snd_device = vc_usecase->in_snd_device;
906 out_snd_device = vc_usecase->out_snd_device;
907 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800908 } else if (voice_extn_compress_voip_is_active(adev)) {
909 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin6c23f382014-08-14 00:00:51 -0700910 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish6a4c3372014-06-25 12:20:37 +0530911 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin6c23f382014-08-14 00:00:51 -0700912 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800913 in_snd_device = voip_usecase->in_snd_device;
914 out_snd_device = voip_usecase->out_snd_device;
915 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800916 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800917 hfp_ucid = audio_extn_hfp_get_usecase();
918 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin6c23f382014-08-14 00:00:51 -0700919 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800920 in_snd_device = hfp_usecase->in_snd_device;
921 out_snd_device = hfp_usecase->out_snd_device;
922 }
Vimal Puthanveed8fa9eab2014-01-07 16:47:47 -0800923 } else if (audio_extn_hfp_is_active(adev)) {
924 hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
925 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
926 in_snd_device = hfp_usecase->in_snd_device;
927 out_snd_device = hfp_usecase->out_snd_device;
928 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700929 }
930 if (usecase->type == PCM_PLAYBACK) {
931 usecase->devices = usecase->stream.out->devices;
932 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700933 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700934 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700935 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700936 if (usecase->stream.out == adev->primary_output &&
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530937 adev->active_input ) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700938 select_devices(adev, adev->active_input->usecase);
939 }
940 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700941 } else if (usecase->type == PCM_CAPTURE) {
942 usecase->devices = usecase->stream.in->device;
943 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700944 if (in_snd_device == SND_DEVICE_NONE) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530945 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530946 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 -0700947 adev->primary_output && !adev->primary_output->standby) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530948 out_device = adev->primary_output->devices;
949 } else if(usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
950 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700951 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530952 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700953 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700954 }
955 }
956
957 if (out_snd_device == usecase->out_snd_device &&
958 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800959 return 0;
960 }
961
sangwoobc677242013-08-08 16:53:43 +0900962 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700963 out_snd_device, platform_get_snd_device_name(out_snd_device),
964 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800966 /*
967 * Limitation: While in call, to do a device switch we need to disable
968 * and enable both RX and TX devices though one of them is same as current
969 * device.
970 */
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800971 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700972 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800973 }
974
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700975 /* Disable current sound devices */
976 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700977 disable_audio_route(adev, usecase);
978 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800979 }
980
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700981 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700982 disable_audio_route(adev, usecase);
983 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800984 }
985
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700986 /* Enable new sound devices */
987 if (out_snd_device != SND_DEVICE_NONE) {
988 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
989 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700990 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800991 }
992
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700993 if (in_snd_device != SND_DEVICE_NONE) {
994 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700995 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700996 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700997
Avinash Vaish8005dc82014-07-24 15:36:33 +0530998 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700999 status = platform_switch_voice_call_device_post(adev->platform,
1000 out_snd_device,
1001 in_snd_device);
Avinash Vaish8005dc82014-07-24 15:36:33 +05301002 enable_audio_route_for_voice_usecases(adev, usecase);
1003 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001004
sangwoo170731f2013-06-08 15:36:36 +09001005 usecase->in_snd_device = in_snd_device;
1006 usecase->out_snd_device = out_snd_device;
1007
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001008 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001009
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301010 /* Rely on amplifier_set_devices to distinguish between in/out devices */
Ethan Chen79c356c2015-06-07 12:26:14 -07001011 amplifier_set_input_devices(in_snd_device);
1012 amplifier_set_output_devices(out_snd_device);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301013
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001014 /* Applicable only on the targets that has external modem.
1015 * Enable device command should be sent to modem only after
1016 * enabling voice call mixer controls
1017 */
1018 if (usecase->type == VOICE_CALL)
1019 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1020 out_snd_device,
1021 in_snd_device);
1022
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301023 ALOGD("%s: done",__func__);
1024
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001025 return status;
1026}
1027
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001028static int stop_input_stream(struct stream_in *in)
1029{
1030 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001031 struct audio_usecase *uc_info;
1032 struct audio_device *adev = in->dev;
1033
Eric Laurentc8400632013-02-14 19:04:54 -08001034 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035
Eric Laurent994a6932013-07-17 11:51:42 -07001036 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001037 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001038 uc_info = get_usecase_from_list(adev, in->usecase);
1039 if (uc_info == NULL) {
1040 ALOGE("%s: Could not find the usecase (%d) in the list",
1041 __func__, in->usecase);
1042 return -EINVAL;
1043 }
1044
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001045 /* Close in-call recording streams */
1046 voice_check_and_stop_incall_rec_usecase(adev, in);
1047
Eric Laurent150dbfe2013-02-27 14:31:02 -08001048 /* 1. Disable stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001049 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001050
1051 /* 2. Disable the tx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001052 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001053
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001054 list_remove(&uc_info->list);
1055 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001056
Eric Laurent994a6932013-07-17 11:51:42 -07001057 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058 return ret;
1059}
1060
1061int start_input_stream(struct stream_in *in)
1062{
1063 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001064 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001065 struct audio_usecase *uc_info;
1066 struct audio_device *adev = in->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301067 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001068
Ramjee Singh240ac652015-07-31 16:12:29 +05301069 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1070 if (get_usecase_from_list(adev, usecase) == NULL)
1071 in->usecase = usecase;
1072
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301073 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1074 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001075
Naresh Tannirucef332d2014-06-04 18:17:56 +05301076 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
1077 ALOGE("%s: sound card is not active/SSR returning error ", __func__);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301078 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301079 goto error_config;
1080 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301081
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001082 /* Check if source matches incall recording usecase criteria */
1083 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1084 if (ret)
1085 goto error_config;
1086 else
1087 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1088
Ramjee Singh240ac652015-07-31 16:12:29 +05301089 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1090 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1091 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1092 goto error_config;
1093 }
1094
Eric Laurentb23d5282013-05-14 15:27:20 -07001095 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001096 if (in->pcm_device_id < 0) {
1097 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1098 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001099 ret = -EINVAL;
1100 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001101 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102
1103 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001104 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001105
1106 if (!uc_info) {
1107 ret = -ENOMEM;
1108 goto error_config;
1109 }
1110
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111 uc_info->id = in->usecase;
1112 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001113 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001114 uc_info->devices = in->device;
1115 uc_info->in_snd_device = SND_DEVICE_NONE;
1116 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001118 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001119 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120
Eric Laurentc8400632013-02-14 19:04:54 -08001121 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301122 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1123
1124 unsigned int flags = PCM_IN;
1125 unsigned int pcm_open_retry_entry_count = 0;
1126
1127 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1128 flags |= PCM_MMAP | PCM_NOIRQ;
1129 pcm_open_retry_entry_count = PROXY_OPEN_RETRY_COUNT;
1130 }
1131
1132 while(1) {
1133 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1134 flags, &in->config);
1135 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1136 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1137 if (in->pcm != NULL) {
1138 pcm_close(in->pcm);
1139 in->pcm = NULL;
1140 }
1141 if (pcm_open_retry_entry_count-- == 0) {
1142 ret = -EIO;
1143 goto error_open;
1144 }
1145 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1146 continue;
1147 }
1148 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001149 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301150
Eric Laurent994a6932013-07-17 11:51:42 -07001151 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001152 return ret;
1153
1154error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08001156
1157error_config:
1158 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001159 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001160
1161 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001162}
1163
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001164/* must be called with out->lock locked */
1165static int send_offload_cmd_l(struct stream_out* out, int command)
1166{
1167 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1168
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001169 if (!cmd) {
1170 ALOGE("failed to allocate mem for command 0x%x", command);
1171 return -ENOMEM;
1172 }
1173
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001174 ALOGVV("%s %d", __func__, command);
1175
1176 cmd->cmd = command;
1177 list_add_tail(&out->offload_cmd_list, &cmd->node);
1178 pthread_cond_signal(&out->offload_cond);
1179 return 0;
1180}
1181
1182/* must be called iwth out->lock locked */
1183static void stop_compressed_output_l(struct stream_out *out)
1184{
1185 out->offload_state = OFFLOAD_STATE_IDLE;
1186 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001187 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001188 if (out->compr != NULL) {
1189 compress_stop(out->compr);
1190 while (out->offload_thread_blocked) {
1191 pthread_cond_wait(&out->cond, &out->lock);
1192 }
1193 }
1194}
1195
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001196bool is_offload_usecase(audio_usecase_t uc_id)
1197{
1198 unsigned int i;
1199 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1200 if (uc_id == offload_usecases[i])
1201 return true;
1202 }
1203 return false;
1204}
1205
1206static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1207{
1208 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1209 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1210 char value[PROPERTY_VALUE_MAX] = {0};
1211
1212 property_get("audio.offload.multiple.enabled", value, NULL);
1213 if (!(atoi(value) || !strncmp("true", value, 4)))
1214 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1215
1216 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1217 for (i = 0; i < num_usecase; i++) {
1218 if (!(adev->offload_usecases_state & (0x1<<i))) {
1219 adev->offload_usecases_state |= 0x1 << i;
1220 ret = offload_usecases[i];
1221 break;
1222 }
1223 }
1224 ALOGV("%s: offload usecase is %d", __func__, ret);
1225 return ret;
1226}
1227
1228static void free_offload_usecase(struct audio_device *adev,
1229 audio_usecase_t uc_id)
1230{
1231 unsigned int i;
1232 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1233 if (offload_usecases[i] == uc_id) {
1234 adev->offload_usecases_state &= ~(0x1<<i);
1235 break;
1236 }
1237 }
1238 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1239}
1240
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001241static void *offload_thread_loop(void *context)
1242{
1243 struct stream_out *out = (struct stream_out *) context;
1244 struct listnode *item;
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001245 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001246
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001247 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1248 set_sched_policy(0, SP_FOREGROUND);
1249 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1250
1251 ALOGV("%s", __func__);
1252 pthread_mutex_lock(&out->lock);
1253 for (;;) {
1254 struct offload_cmd *cmd = NULL;
1255 stream_callback_event_t event;
1256 bool send_callback = false;
1257
1258 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1259 __func__, list_empty(&out->offload_cmd_list),
1260 out->offload_state);
1261 if (list_empty(&out->offload_cmd_list)) {
1262 ALOGV("%s SLEEPING", __func__);
1263 pthread_cond_wait(&out->offload_cond, &out->lock);
1264 ALOGV("%s RUNNING", __func__);
1265 continue;
1266 }
1267
1268 item = list_head(&out->offload_cmd_list);
1269 cmd = node_to_item(item, struct offload_cmd, node);
1270 list_remove(item);
1271
1272 ALOGVV("%s STATE %d CMD %d out->compr %p",
1273 __func__, out->offload_state, cmd->cmd, out->compr);
1274
1275 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1276 free(cmd);
1277 break;
1278 }
1279
1280 if (out->compr == NULL) {
1281 ALOGE("%s: Compress handle is NULL", __func__);
1282 pthread_cond_signal(&out->cond);
1283 continue;
1284 }
1285 out->offload_thread_blocked = true;
1286 pthread_mutex_unlock(&out->lock);
1287 send_callback = false;
1288 switch(cmd->cmd) {
1289 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Steve Kondik05c17962015-02-25 00:55:50 -08001290 ALOGV("copl(%x):calling compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001291 compress_wait(out->compr, -1);
Steve Kondik05c17962015-02-25 00:55:50 -08001292 ALOGV("copl(%x):out of compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001293 send_callback = true;
1294 event = STREAM_CBK_EVENT_WRITE_READY;
1295 break;
1296 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001297 ret = compress_next_track(out->compr);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301298 if(ret == 0) {
Steve Kondik05c17962015-02-25 00:55:50 -08001299 ALOGV("copl(%p):calling compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301300 ret = compress_partial_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001301 ALOGV("copl(%p):out of compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301302 if (ret < 0)
1303 ret = -errno;
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301304 }
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301305 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001306 compress_drain(out->compr);
1307 else
1308 ALOGE("%s: Next track returned error %d",__func__, ret);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301309
1310 if (ret != -ENETRESET) {
1311 send_callback = true;
1312 event = STREAM_CBK_EVENT_DRAIN_READY;
1313
1314 /* Resend the metadata for next iteration */
1315 out->send_new_metadata = 1;
1316 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1317 } else
1318 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001319 break;
1320 case OFFLOAD_CMD_DRAIN:
Steve Kondik05c17962015-02-25 00:55:50 -08001321 ALOGV("copl(%x):calling compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001322 compress_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001323 ALOGV("copl(%x):out of compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001324 send_callback = true;
1325 event = STREAM_CBK_EVENT_DRAIN_READY;
1326 break;
1327 default:
1328 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1329 break;
1330 }
1331 pthread_mutex_lock(&out->lock);
1332 out->offload_thread_blocked = false;
1333 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001334 if (send_callback) {
Ravi Kumar Alamanda3d316172014-12-02 19:21:51 -08001335 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001336 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001337 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001338 free(cmd);
1339 }
1340
1341 pthread_cond_signal(&out->cond);
1342 while (!list_empty(&out->offload_cmd_list)) {
1343 item = list_head(&out->offload_cmd_list);
1344 list_remove(item);
1345 free(node_to_item(item, struct offload_cmd, node));
1346 }
1347 pthread_mutex_unlock(&out->lock);
1348
1349 return NULL;
1350}
1351
1352static int create_offload_callback_thread(struct stream_out *out)
1353{
1354 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1355 list_init(&out->offload_cmd_list);
1356 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1357 offload_thread_loop, out);
1358 return 0;
1359}
1360
1361static int destroy_offload_callback_thread(struct stream_out *out)
1362{
1363 pthread_mutex_lock(&out->lock);
1364 stop_compressed_output_l(out);
1365 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1366
1367 pthread_mutex_unlock(&out->lock);
1368 pthread_join(out->offload_thread, (void **) NULL);
1369 pthread_cond_destroy(&out->offload_cond);
1370
1371 return 0;
1372}
1373
Eric Laurent07eeafd2013-10-06 12:52:49 -07001374static bool allow_hdmi_channel_config(struct audio_device *adev)
1375{
1376 struct listnode *node;
1377 struct audio_usecase *usecase;
1378 bool ret = true;
1379
1380 list_for_each(node, &adev->usecase_list) {
1381 usecase = node_to_item(node, struct audio_usecase, list);
1382 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1383 /*
1384 * If voice call is already existing, do not proceed further to avoid
1385 * disabling/enabling both RX and TX devices, CSD calls, etc.
1386 * Once the voice call done, the HDMI channels can be configured to
1387 * max channels of remaining use cases.
1388 */
1389 if (usecase->id == USECASE_VOICE_CALL) {
1390 ALOGD("%s: voice call is active, no change in HDMI channels",
1391 __func__);
1392 ret = false;
1393 break;
1394 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1395 ALOGD("%s: multi channel playback is active, "
1396 "no change in HDMI channels", __func__);
1397 ret = false;
1398 break;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001399 } else if (is_offload_usecase(usecase->id) &&
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301400 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin3ed162b2014-02-24 17:56:01 -08001401 ALOGD("%s: multi-channel(%x) compress offload playback is active, "
1402 "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
1403 ret = false;
1404 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001405 }
1406 }
1407 }
1408 return ret;
1409}
1410
1411static int check_and_set_hdmi_channels(struct audio_device *adev,
1412 unsigned int channels)
1413{
1414 struct listnode *node;
1415 struct audio_usecase *usecase;
1416
1417 /* Check if change in HDMI channel config is allowed */
1418 if (!allow_hdmi_channel_config(adev))
1419 return 0;
1420
1421 if (channels == adev->cur_hdmi_channels) {
Mingming Yin10fef6a2013-11-26 17:17:01 -08001422 ALOGD("%s: Requested channels are same as current channels(%d)", __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001423 return 0;
1424 }
1425
1426 platform_set_hdmi_channels(adev->platform, channels);
1427 adev->cur_hdmi_channels = channels;
1428
1429 /*
1430 * Deroute all the playback streams routed to HDMI so that
1431 * the back end is deactivated. Note that backend will not
1432 * be deactivated if any one stream is connected to it.
1433 */
1434 list_for_each(node, &adev->usecase_list) {
1435 usecase = node_to_item(node, struct audio_usecase, list);
1436 if (usecase->type == PCM_PLAYBACK &&
1437 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001438 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001439 }
1440 }
1441
1442 /*
1443 * Enable all the streams disabled above. Now the HDMI backend
1444 * will be activated with new channel configuration
1445 */
1446 list_for_each(node, &adev->usecase_list) {
1447 usecase = node_to_item(node, struct audio_usecase, list);
1448 if (usecase->type == PCM_PLAYBACK &&
1449 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001450 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001451 }
1452 }
1453
1454 return 0;
1455}
1456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001457static int stop_output_stream(struct stream_out *out)
1458{
1459 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001460 struct audio_usecase *uc_info;
1461 struct audio_device *adev = out->dev;
1462
Eric Laurent994a6932013-07-17 11:51:42 -07001463 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001464 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001465 uc_info = get_usecase_from_list(adev, out->usecase);
1466 if (uc_info == NULL) {
1467 ALOGE("%s: Could not find the usecase (%d) in the list",
1468 __func__, out->usecase);
1469 return -EINVAL;
1470 }
1471
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001472 if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001473 if (adev->visualizer_stop_output != NULL)
1474 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1475 if (adev->offload_effects_stop_output != NULL)
1476 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1477 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001478
Eric Laurent150dbfe2013-02-27 14:31:02 -08001479 /* 1. Get and set stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001480 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001481
1482 /* 2. Disable the rx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001483 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001484
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001485 list_remove(&uc_info->list);
1486 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487
Eric Laurentda46bfb2014-08-25 22:39:29 -05001488 audio_extn_extspk_update(adev->extspk);
1489
Eric Laurent07eeafd2013-10-06 12:52:49 -07001490 /* Must be called after removing the usecase from list */
1491 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1492 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1493
Eric Laurent994a6932013-07-17 11:51:42 -07001494 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001495 return ret;
1496}
1497
1498int start_output_stream(struct stream_out *out)
1499{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001500 int ret = 0;
Mingming Yin6c344432014-05-01 15:37:31 -07001501 int sink_channels = 0;
1502 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001503 struct audio_usecase *uc_info;
1504 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301505 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001507 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1508 ret = -EINVAL;
1509 goto error_config;
1510 }
1511
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301512 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1513 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1514 out->devices);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301515
Naresh Tannirucef332d2014-06-04 18:17:56 +05301516 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301517 ALOGE("%s: sound card is not active/SSR returning error", __func__);
1518 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301519 goto error_config;
1520 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301521
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301522 ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
1523 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001524 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 if (out->pcm_device_id < 0) {
1526 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1527 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001528 ret = -EINVAL;
1529 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001530 }
1531
1532 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001533
1534 if (!uc_info) {
1535 ret = -ENOMEM;
1536 goto error_config;
1537 }
1538
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001539 uc_info->id = out->usecase;
1540 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001541 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001542 uc_info->devices = out->devices;
1543 uc_info->in_snd_device = SND_DEVICE_NONE;
1544 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001545
Eric Laurent07eeafd2013-10-06 12:52:49 -07001546 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001547 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Mingming Yin6c344432014-05-01 15:37:31 -07001548 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1549 if (!strncmp("true", prop_value, 4)) {
1550 sink_channels = platform_edid_get_max_channels(out->dev->platform);
1551 ALOGD("%s: set HDMI channel count[%d] based on sink capability", __func__, sink_channels);
1552 check_and_set_hdmi_channels(adev, sink_channels);
1553 } else {
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001554 if (is_offload_usecase(out->usecase))
Mingming Yin6c344432014-05-01 15:37:31 -07001555 check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in);
1556 else
1557 check_and_set_hdmi_channels(adev, out->config.channels);
1558 }
Mingming Yin10fef6a2013-11-26 17:17:01 -08001559 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001560
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001561 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001563 select_devices(adev, out->usecase);
1564
Eric Laurentda46bfb2014-08-25 22:39:29 -05001565 audio_extn_extspk_update(adev->extspk);
1566
Steve Kondik3abbbc82014-11-29 14:14:43 -08001567 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1568 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
1569
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001570 if (!is_offload_usecase(out->usecase)) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301571 unsigned int flags = PCM_OUT;
1572 unsigned int pcm_open_retry_count = 0;
1573 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1574 flags |= PCM_MMAP | PCM_NOIRQ;
1575 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1576 } else
1577 flags |= PCM_MONOTONIC;
1578
1579 while (1) {
1580 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1581 flags, &out->config);
1582 if (out->pcm && !pcm_is_ready(out->pcm)) {
1583 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1584 if (out->pcm != NULL) {
1585 pcm_close(out->pcm);
1586 out->pcm = NULL;
1587 }
1588 if (pcm_open_retry_count-- == 0) {
1589 ret = -EIO;
1590 goto error_open;
1591 }
1592 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1593 continue;
1594 }
1595 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001596 }
1597 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001598 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001599 out->compr = compress_open(adev->snd_card,
1600 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001601 COMPRESS_IN, &out->compr_config);
1602 if (out->compr && !is_compress_ready(out->compr)) {
1603 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1604 compress_close(out->compr);
1605 out->compr = NULL;
1606 ret = -EIO;
1607 goto error_open;
1608 }
1609 if (out->offload_callback)
1610 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001611
Fred Oh1483d8a2015-03-04 18:42:34 -08001612 /* Since small bufs uses blocking writes, a write will be blocked
1613 for the default max poll time (20s) in the event of an SSR.
1614 Reduce the poll time to observe and deal with SSR faster.
1615 */
1616 if (out->use_small_bufs) {
1617 compress_set_max_poll_wait(out->compr, 1000);
1618 }
1619
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08001620#ifdef DS1_DOLBY_DDP_ENABLED
1621 if (audio_extn_is_dolby_format(out->format))
1622 audio_extn_dolby_send_ddp_endp_params(adev);
1623#endif
1624
Eric Laurentc4aef752013-09-12 17:45:53 -07001625 if (adev->visualizer_start_output != NULL)
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001626 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1627 if (adev->offload_effects_start_output != NULL)
1628 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001629 }
Eric Laurent994a6932013-07-17 11:51:42 -07001630 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001631 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001632error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001633 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001634error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001635 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001636}
1637
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001638static int check_input_parameters(uint32_t sample_rate,
1639 audio_format_t format,
1640 int channel_count)
1641{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001642 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001643
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001644 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001645 !voice_extn_compress_voip_is_format_supported(format) &&
1646 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001647
1648 switch (channel_count) {
1649 case 1:
1650 case 2:
1651 case 6:
1652 break;
1653 default:
1654 ret = -EINVAL;
1655 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656
1657 switch (sample_rate) {
1658 case 8000:
1659 case 11025:
1660 case 12000:
1661 case 16000:
1662 case 22050:
1663 case 24000:
1664 case 32000:
1665 case 44100:
1666 case 48000:
1667 break;
1668 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001669 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001670 }
1671
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001672 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001673}
1674
1675static size_t get_input_buffer_size(uint32_t sample_rate,
1676 audio_format_t format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001677 int channel_count,
1678 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679{
1680 size_t size = 0;
1681
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001682 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1683 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001685 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001686 if (is_low_latency)
1687 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001688 /* ToDo: should use frame_size computed based on the format and
1689 channel_count here. */
1690 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001691
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001692 /* make sure the size is multiple of 32 bytes
1693 * At 48 kHz mono 16-bit PCM:
1694 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1695 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1696 */
1697 size += 0x1f;
1698 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001699
1700 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001701}
1702
1703static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1704{
1705 struct stream_out *out = (struct stream_out *)stream;
1706
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001707 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708}
1709
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301710static int out_set_sample_rate(struct audio_stream *stream __unused,
1711 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001712{
1713 return -ENOSYS;
1714}
1715
1716static size_t out_get_buffer_size(const struct audio_stream *stream)
1717{
1718 struct stream_out *out = (struct stream_out *)stream;
1719
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001720 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001721 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001722 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1723 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001724
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301725 return out->config.period_size *
1726 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727}
1728
1729static uint32_t out_get_channels(const struct audio_stream *stream)
1730{
1731 struct stream_out *out = (struct stream_out *)stream;
1732
1733 return out->channel_mask;
1734}
1735
1736static audio_format_t out_get_format(const struct audio_stream *stream)
1737{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001738 struct stream_out *out = (struct stream_out *)stream;
1739
1740 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741}
1742
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301743static int out_set_format(struct audio_stream *stream __unused,
1744 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001745{
1746 return -ENOSYS;
1747}
1748
1749static int out_standby(struct audio_stream *stream)
1750{
1751 struct stream_out *out = (struct stream_out *)stream;
1752 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301754 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1755 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001756 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1757 /* Ignore standby in case of voip call because the voip output
1758 * stream is closed in adev_close_output_stream()
1759 */
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301760 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001761 return 0;
1762 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001764 pthread_mutex_lock(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001766 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07001767
1768 amplifier_output_stream_standby((struct audio_stream_out *) stream);
1769
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770 out->standby = true;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001771 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001772 if (out->pcm) {
1773 pcm_close(out->pcm);
1774 out->pcm = NULL;
1775 }
1776 } else {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301777 ALOGD("copl(%x):standby", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001778 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001779 out->gapless_mdata.encoder_delay = 0;
1780 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001781 if (out->compr != NULL) {
1782 compress_close(out->compr);
1783 out->compr = NULL;
1784 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001785 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001787 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001788 }
1789 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001790 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 return 0;
1792}
1793
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301794static int out_dump(const struct audio_stream *stream __unused,
1795 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796{
1797 return 0;
1798}
1799
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001800static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1801{
1802 int ret = 0;
1803 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001804 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001805 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001806 tmp_mdata.encoder_delay = 0;
1807 tmp_mdata.encoder_padding = 0;
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001808
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001809 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001810 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001811 return -EINVAL;
1812 }
1813
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001814 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1815 if (ret >= 0) {
1816 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1817 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1818 ALOGV("ADTS format is set in offload mode");
1819 }
1820 out->send_new_metadata = 1;
1821 }
1822
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001823#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001824 if (out->format == AUDIO_FORMAT_FLAC) {
1825 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1826 if (ret >= 0) {
1827 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1828 out->send_new_metadata = 1;
1829 }
1830 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1831 if (ret >= 0) {
1832 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1833 out->send_new_metadata = 1;
1834 }
1835 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1836 if (ret >= 0) {
1837 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1838 out->send_new_metadata = 1;
1839 }
1840 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1841 if (ret >= 0) {
1842 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1843 out->send_new_metadata = 1;
1844 }
1845 }
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001846#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001847
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001848 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1849 if(ret >= 0)
1850 is_meta_data_params = true;
1851 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1852 if(ret >= 0 )
1853 is_meta_data_params = true;
1854 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1855 if(ret >= 0 )
1856 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001857 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1858 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001859 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001861 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001862 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1863 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001864 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001865 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001866 }
1867
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001868 if(!is_meta_data_params) {
1869 ALOGV("%s: Not gapless meta data params", __func__);
1870 return 0;
1871 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001872 out->gapless_mdata = tmp_mdata;
1873 out->send_new_metadata = 1;
1874 ALOGV("%s new encoder delay %u and padding %u", __func__,
1875 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1876
Steve Kondikba3b35d2014-07-18 01:49:48 -07001877 if(out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
1878 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
1879 if (ret >= 0) {
1880 out->compr_config.codec->format = atoi(value);
1881 }
1882 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
1883 if (ret >= 0) {
1884 out->compr_config.codec->options.wma.super_block_align = atoi(value);
1885 }
1886 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
1887 if (ret >= 0) {
1888 out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
1889 }
1890 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
1891 if (ret >= 0) {
1892 out->compr_config.codec->options.wma.channelmask = atoi(value);
1893 }
1894 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
1895 if (ret >= 0) {
1896 out->compr_config.codec->options.wma.encodeopt = atoi(value);
1897 }
1898 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
1899 if (ret >= 0) {
1900 out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
1901 }
1902 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
1903 if (ret >= 0) {
1904 out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
1905 }
1906 ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
1907 out->compr_config.codec->format,
1908 out->compr_config.codec->options.wma.super_block_align,
1909 out->compr_config.codec->options.wma.bits_per_sample,
1910 out->compr_config.codec->options.wma.channelmask,
1911 out->compr_config.codec->options.wma.encodeopt,
1912 out->compr_config.codec->options.wma.encodeopt1,
1913 out->compr_config.codec->options.wma.encodeopt2);
1914 }
1915
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001916 return 0;
1917}
1918
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301919static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1920{
1921 return out == adev->primary_output || out == adev->voice_tx_output;
1922}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001923
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001924static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1925{
1926 struct stream_out *out = (struct stream_out *)stream;
1927 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001928 struct audio_usecase *usecase;
1929 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001930 struct str_parms *parms;
1931 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001932 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001933 bool select_new_device = false;
Steve Kondik3abbbc82014-11-29 14:14:43 -08001934 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001935
sangwoobc677242013-08-08 16:53:43 +09001936 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001937 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001938 parms = str_parms_create_str(kvpairs);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001939 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1940 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001941 val = atoi(value);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942 pthread_mutex_lock(&out->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001943 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001944
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001945 /*
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301946 * When HDMI cable is unplugged/usb hs is disconnected the
1947 * music playback is paused and the policy manager sends routing=0
1948 * But the audioflingercontinues to write data until standby time
1949 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001950 * Avoid this by routing audio to speaker until standby.
1951 */
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301952 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
Steve Kondikeadb6c82014-09-03 18:40:06 -07001953 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
1954 out->devices == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001955 val == AUDIO_DEVICE_NONE) {
1956 val = AUDIO_DEVICE_OUT_SPEAKER;
1957 }
1958
1959 /*
1960 * select_devices() call below switches all the usecases on the same
1961 * backend to the new device. Refer to check_usecases_codec_backend() in
1962 * the select_devices(). But how do we undo this?
1963 *
1964 * For example, music playback is active on headset (deep-buffer usecase)
1965 * and if we go to ringtones and select a ringtone, low-latency usecase
1966 * will be started on headset+speaker. As we can't enable headset+speaker
1967 * and headset devices at the same time, select_devices() switches the music
1968 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1969 * So when the ringtone playback is completed, how do we undo the same?
1970 *
1971 * We are relying on the out_set_parameters() call on deep-buffer output,
1972 * once the ringtone playback is ended.
1973 * NOTE: We should not check if the current devices are same as new devices.
1974 * Because select_devices() must be called to switch back the music
1975 * playback to headset.
1976 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001977 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001978 out->devices = val;
1979
1980 if (!out->standby)
1981 select_devices(adev, out->usecase);
1982
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001983 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301984 output_drives_call(adev, out)) {
1985 adev->current_call_output = out;
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001986 if (!adev->voice.in_call)
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301987 ret = voice_start_call(adev);
1988 else
1989 voice_update_devices_for_all_voice_usecases(adev);
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001990 }
1991 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001992
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001993 if ((adev->mode == AUDIO_MODE_NORMAL) &&
1994 adev->voice.in_call &&
1995 output_drives_call(adev, out)) {
1996 ret = voice_stop_call(adev);
1997 adev->current_call_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001998 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001999
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002000 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002001 pthread_mutex_unlock(&out->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05002002
2003 /*handles device and call state changes*/
2004 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002005 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002006
2007 if (out == adev->primary_output) {
2008 pthread_mutex_lock(&adev->lock);
2009 audio_extn_set_parameters(adev, parms);
2010 pthread_mutex_unlock(&adev->lock);
2011 }
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002012 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002013 pthread_mutex_lock(&out->lock);
Steve Kondikba3b35d2014-07-18 01:49:48 -07002014 ret = parse_compress_metadata(out, parms);
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002015 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002016 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002017
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002018 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002019 ALOGV("%s: exit: code(%d)", __func__, status);
2020 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021}
2022
2023static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2024{
2025 struct stream_out *out = (struct stream_out *)stream;
2026 struct str_parms *query = str_parms_create_str(keys);
2027 char *str;
2028 char value[256];
2029 struct str_parms *reply = str_parms_create();
2030 size_t i, j;
2031 int ret;
2032 bool first = true;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002033
2034 if (!query || !reply) {
2035 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2036 return NULL;
2037 }
2038
Eric Laurent994a6932013-07-17 11:51:42 -07002039 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2041 if (ret >= 0) {
2042 value[0] = '\0';
2043 i = 0;
2044 while (out->supported_channel_masks[i] != 0) {
2045 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2046 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2047 if (!first) {
2048 strcat(value, "|");
2049 }
2050 strcat(value, out_channels_name_to_enum_table[j].name);
2051 first = false;
2052 break;
2053 }
2054 }
2055 i++;
2056 }
2057 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2058 str = str_parms_to_str(reply);
2059 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002060 voice_extn_out_get_parameters(out, query, reply);
2061 str = str_parms_to_str(reply);
2062 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella2e032352014-01-29 12:52:19 -08002063 free(str);
2064 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002065 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066 }
2067 str_parms_destroy(query);
2068 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002069 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002070 return str;
2071}
2072
2073static uint32_t out_get_latency(const struct audio_stream_out *stream)
2074{
2075 struct stream_out *out = (struct stream_out *)stream;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002076 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002077
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002078 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002079 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002080 } else {
2081 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002082 (out->config.rate);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002083 }
2084
Anish Kumar1a0594f2014-12-09 04:01:39 +05302085 ALOGV("%s: Latency %d", __func__, latency);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002086 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002087}
2088
2089static int out_set_volume(struct audio_stream_out *stream, float left,
2090 float right)
2091{
Eric Laurenta9024de2013-04-04 09:19:12 -07002092 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002093 int volume[2];
2094
Eric Laurenta9024de2013-04-04 09:19:12 -07002095 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2096 /* only take left channel into account: the API is for stereo anyway */
2097 out->muted = (left == 0.0f);
2098 return 0;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002099 } else if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002100 char mixer_ctl_name[128];
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002101 struct audio_device *adev = out->dev;
2102 struct mixer_ctl *ctl;
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002103 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2104 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002105
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002106 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2107 "Compress Playback %d Volume", pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2109 if (!ctl) {
2110 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2111 __func__, mixer_ctl_name);
2112 return -EINVAL;
2113 }
2114 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2115 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2116 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2117 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002118 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 return -ENOSYS;
2121}
2122
2123static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2124 size_t bytes)
2125{
2126 struct stream_out *out = (struct stream_out *)stream;
2127 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302128 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002129 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002130
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002131 pthread_mutex_lock(&out->lock);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302132
Naresh Tannirucef332d2014-06-04 18:17:56 +05302133 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
2134 if (out->pcm) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302135 ALOGD(" %s: sound card is not active/SSR state", __func__);
2136 ret= -ENETRESET;
2137 goto exit;
Alexy Joseph55204352014-10-06 12:15:01 -07002138 } else if (is_offload_usecase(out->usecase)) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302139 //during SSR for compress usecase we should return error to flinger
2140 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2141 pthread_mutex_unlock(&out->lock);
2142 return -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302143 }
2144 }
2145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002147 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002148 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002149 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2150 ret = voice_extn_compress_voip_start_output_stream(out);
2151 else
2152 ret = start_output_stream(out);
Ethan Chen79c356c2015-06-07 12:26:14 -07002153
2154 if (ret == 0)
2155 amplifier_output_stream_start(stream,
2156 is_offload_usecase(out->usecase));
2157
Eric Laurent150dbfe2013-02-27 14:31:02 -08002158 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002159 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002160 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002161 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002162 goto exit;
2163 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002165
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002166 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002167 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002168 if (out->send_new_metadata) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302169 ALOGD("copl(%x):send new gapless metadata", (unsigned int)out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002170 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2171 out->send_new_metadata = 0;
2172 }
2173
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002174 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302175 if (ret < 0)
2176 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002177 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002178 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302179 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002180 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302181 } else if (-ENETRESET == ret) {
2182 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2183 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2184 pthread_mutex_unlock(&out->lock);
2185 out_standby(&out->stream.common);
2186 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002187 }
Naresh Tannirucef332d2014-06-04 18:17:56 +05302188 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 compress_start(out->compr);
2190 out->playback_started = 1;
2191 out->offload_state = OFFLOAD_STATE_PLAYING;
2192 }
2193 pthread_mutex_unlock(&out->lock);
2194 return ret;
2195 } else {
2196 if (out->pcm) {
2197 if (out->muted)
2198 memset((void *)buffer, 0, bytes);
2199 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302200 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2201 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2202 else
2203 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302204 if (ret < 0)
2205 ret = -errno;
2206 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002207 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002208 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002209 }
2210
2211exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302212 /* ToDo: There may be a corner case when SSR happens back to back during
2213 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302214 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302215 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302216 }
2217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002218 pthread_mutex_unlock(&out->lock);
2219
2220 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002221 if (out->pcm)
2222 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302223 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302224 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302225 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302226 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302227 out->standby = true;
2228 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002229 out_standby(&out->stream.common);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002230 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
2231 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232 }
2233 return bytes;
2234}
2235
2236static int out_get_render_position(const struct audio_stream_out *stream,
2237 uint32_t *dsp_frames)
2238{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002239 struct stream_out *out = (struct stream_out *)stream;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002240 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
2241 ssize_t ret = 0;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002242 *dsp_frames = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002243 pthread_mutex_lock(&out->lock);
2244 if (out->compr != NULL) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302245 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002246 &out->sample_rate);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302247 if (ret < 0)
2248 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002249 ALOGVV("%s rendered frames %d sample_rate %d",
2250 __func__, *dsp_frames, out->sample_rate);
2251 }
2252 pthread_mutex_unlock(&out->lock);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302253 if (-ENETRESET == ret) {
2254 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2255 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2256 return -EINVAL;
2257 } else if(ret < 0) {
Steve Kondik81506242014-07-21 16:12:57 -07002258 if (out->compr == NULL) {
2259 return 0;
2260 }
2261 ALOGE(" ERROR: Unable to get time stamp from compress driver ret=%d", ret);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302262 return -EINVAL;
2263 } else {
2264 return 0;
2265 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002266 } else
2267 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002268}
2269
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302270static int out_add_audio_effect(const struct audio_stream *stream __unused,
2271 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272{
2273 return 0;
2274}
2275
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302276static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2277 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002278{
2279 return 0;
2280}
2281
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302282static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2283 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002284{
2285 return -EINVAL;
2286}
2287
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002288static int out_get_presentation_position(const struct audio_stream_out *stream,
2289 uint64_t *frames, struct timespec *timestamp)
2290{
2291 struct stream_out *out = (struct stream_out *)stream;
2292 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002293 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002294
2295 pthread_mutex_lock(&out->lock);
2296
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002297 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002298 if (out->compr != NULL) {
2299 compress_get_tstamp(out->compr, &dsp_frames,
2300 &out->sample_rate);
2301 ALOGVV("%s rendered frames %ld sample_rate %d",
2302 __func__, dsp_frames, out->sample_rate);
2303 *frames = dsp_frames;
2304 ret = 0;
2305 /* this is the best we can do */
2306 clock_gettime(CLOCK_MONOTONIC, timestamp);
2307 }
2308 } else {
2309 if (out->pcm) {
2310 size_t avail;
2311 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2312 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002313 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002314 // This adjustment accounts for buffering after app processor.
2315 // It is based on estimated DSP latency per use case, rather than exact.
2316 signed_frames -=
2317 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2318
Eric Laurent949a0892013-09-20 09:20:13 -07002319 // It would be unusual for this value to be negative, but check just in case ...
2320 if (signed_frames >= 0) {
2321 *frames = signed_frames;
2322 ret = 0;
2323 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002324 }
2325 }
2326 }
2327
2328 pthread_mutex_unlock(&out->lock);
2329
2330 return ret;
2331}
2332
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002333static int out_set_callback(struct audio_stream_out *stream,
2334 stream_callback_t callback, void *cookie)
2335{
2336 struct stream_out *out = (struct stream_out *)stream;
2337
2338 ALOGV("%s", __func__);
2339 pthread_mutex_lock(&out->lock);
2340 out->offload_callback = callback;
2341 out->offload_cookie = cookie;
2342 pthread_mutex_unlock(&out->lock);
2343 return 0;
2344}
2345
2346static int out_pause(struct audio_stream_out* stream)
2347{
2348 struct stream_out *out = (struct stream_out *)stream;
2349 int status = -ENOSYS;
2350 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002351 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302352 ALOGD("copl(%x):pause compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002353 pthread_mutex_lock(&out->lock);
2354 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302355 struct audio_device *adev = out->dev;
2356 int snd_scard_state = get_snd_card_state(adev);
2357
2358 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2359 status = compress_pause(out->compr);
2360
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002361 out->offload_state = OFFLOAD_STATE_PAUSED;
2362 }
2363 pthread_mutex_unlock(&out->lock);
2364 }
2365 return status;
2366}
2367
2368static int out_resume(struct audio_stream_out* stream)
2369{
2370 struct stream_out *out = (struct stream_out *)stream;
2371 int status = -ENOSYS;
2372 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002373 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302374 ALOGD("copl(%x):resume compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002375 status = 0;
2376 pthread_mutex_lock(&out->lock);
2377 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302378 struct audio_device *adev = out->dev;
2379 int snd_scard_state = get_snd_card_state(adev);
2380
2381 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2382 status = compress_resume(out->compr);
2383
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002384 out->offload_state = OFFLOAD_STATE_PLAYING;
2385 }
2386 pthread_mutex_unlock(&out->lock);
2387 }
2388 return status;
2389}
2390
2391static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2392{
2393 struct stream_out *out = (struct stream_out *)stream;
2394 int status = -ENOSYS;
2395 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002396 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002397 pthread_mutex_lock(&out->lock);
2398 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2399 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2400 else
2401 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2402 pthread_mutex_unlock(&out->lock);
2403 }
2404 return status;
2405}
2406
2407static int out_flush(struct audio_stream_out* stream)
2408{
2409 struct stream_out *out = (struct stream_out *)stream;
2410 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002411 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302412 ALOGD("copl(%x):calling compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002413 pthread_mutex_lock(&out->lock);
2414 stop_compressed_output_l(out);
2415 pthread_mutex_unlock(&out->lock);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302416 ALOGD("copl(%x):out of compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002417 return 0;
2418 }
2419 return -ENOSYS;
2420}
2421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422/** audio_stream_in implementation **/
2423static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2424{
2425 struct stream_in *in = (struct stream_in *)stream;
2426
2427 return in->config.rate;
2428}
2429
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302430static int in_set_sample_rate(struct audio_stream *stream __unused,
2431 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002432{
2433 return -ENOSYS;
2434}
2435
2436static size_t in_get_buffer_size(const struct audio_stream *stream)
2437{
2438 struct stream_in *in = (struct stream_in *)stream;
2439
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002440 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2441 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002442 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2443 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002444
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302445 return in->config.period_size *
Steve Kondik3abbbc82014-11-29 14:14:43 -08002446 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447}
2448
2449static uint32_t in_get_channels(const struct audio_stream *stream)
2450{
2451 struct stream_in *in = (struct stream_in *)stream;
2452
2453 return in->channel_mask;
2454}
2455
2456static audio_format_t in_get_format(const struct audio_stream *stream)
2457{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002458 struct stream_in *in = (struct stream_in *)stream;
2459
2460 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002461}
2462
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302463static int in_set_format(struct audio_stream *stream __unused,
2464 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465{
2466 return -ENOSYS;
2467}
2468
2469static int in_standby(struct audio_stream *stream)
2470{
2471 struct stream_in *in = (struct stream_in *)stream;
2472 struct audio_device *adev = in->dev;
2473 int status = 0;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302474 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2475 stream, in->usecase, use_case_table[in->usecase]);
2476
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002477
2478 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2479 /* Ignore standby in case of voip call because the voip input
2480 * stream is closed in adev_close_input_stream()
2481 */
2482 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2483 return status;
2484 }
2485
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002486 pthread_mutex_lock(&in->lock);
2487 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002488 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07002489
2490 amplifier_input_stream_standby((struct audio_stream_in *) stream);
2491
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002492 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002493 if (in->pcm) {
2494 pcm_close(in->pcm);
2495 in->pcm = NULL;
2496 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002497 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002498 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002499 }
2500 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002501 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002502 return status;
2503}
2504
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302505static int in_dump(const struct audio_stream *stream __unused,
2506 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002507{
2508 return 0;
2509}
2510
2511static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2512{
2513 struct stream_in *in = (struct stream_in *)stream;
2514 struct audio_device *adev = in->dev;
2515 struct str_parms *parms;
2516 char *str;
2517 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002518 int ret = 0, val = 0, err;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002519 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302521 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 parms = str_parms_create_str(kvpairs);
2523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 pthread_mutex_lock(&in->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002525 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002526
2527 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2528 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002529 val = atoi(value);
2530 /* no audio source uses val == 0 */
2531 if ((in->source != val) && (val != 0)) {
2532 in->source = val;
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002533 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2534 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2535 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2536 (in->config.rate == 8000 || in->config.rate == 16000) &&
Steve Kondikb6ab1fa2015-02-06 16:55:26 -08002537 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002538 err = voice_extn_compress_voip_open_input_stream(in);
2539 if (err != 0) {
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002540 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002541 __func__, err);
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002542 }
2543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002544 }
2545 }
2546
Steve Kondik3abbbc82014-11-29 14:14:43 -08002547 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2548
2549 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550 val = atoi(value);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302551 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002552 in->device = val;
2553 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002554 if (!in->standby)
Steve Kondik3abbbc82014-11-29 14:14:43 -08002555 status = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002556 }
2557 }
2558
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002559done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002560 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002561 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562
2563 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002564 ALOGV("%s: exit: status(%d)", __func__, status);
2565 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002566}
2567
2568static char* in_get_parameters(const struct audio_stream *stream,
2569 const char *keys)
2570{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002571 struct stream_in *in = (struct stream_in *)stream;
2572 struct str_parms *query = str_parms_create_str(keys);
2573 char *str;
2574 char value[256];
2575 struct str_parms *reply = str_parms_create();
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002576
2577 if (!query || !reply) {
2578 ALOGE("in_get_parameters: failed to create query or reply");
2579 return NULL;
2580 }
2581
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002582 ALOGV("%s: enter: keys - %s", __func__, keys);
2583
2584 voice_extn_in_get_parameters(in, query, reply);
2585
2586 str = str_parms_to_str(reply);
2587 str_parms_destroy(query);
2588 str_parms_destroy(reply);
2589
2590 ALOGV("%s: exit: returns - %s", __func__, str);
2591 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592}
2593
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302594static int in_set_gain(struct audio_stream_in *stream __unused,
2595 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596{
2597 return 0;
2598}
2599
2600static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2601 size_t bytes)
2602{
2603 struct stream_in *in = (struct stream_in *)stream;
2604 struct audio_device *adev = in->dev;
2605 int i, ret = -1;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302606 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002608 pthread_mutex_lock(&in->lock);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302609
2610 if (in->pcm) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302611 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302612 ALOGD(" %s: sound card is not active/SSR state", __func__);
2613 ret= -ENETRESET;
2614 goto exit;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302615 }
2616 }
2617
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002619 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002620 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2621 ret = voice_extn_compress_voip_start_input_stream(in);
2622 else
2623 ret = start_input_stream(in);
Ethan Chen79c356c2015-06-07 12:26:14 -07002624
2625 if (ret == 0)
2626 amplifier_input_stream_start(stream);
2627
Eric Laurent150dbfe2013-02-27 14:31:02 -08002628 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002629 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630 goto exit;
2631 }
2632 in->standby = 0;
2633 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002634
2635 if (in->pcm) {
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302636 if (audio_extn_ssr_get_enabled() &&
2637 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002638 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002639 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2640 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302641 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2642 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002643 else
2644 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302645 if (ret < 0)
2646 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 }
2648
2649 /*
2650 * Instead of writing zeroes here, we could trust the hardware
2651 * to always provide zeroes when muted.
2652 */
Pavan Chikkala6c183fd2014-12-04 10:48:28 +05302653 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2654 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 memset(buffer, 0, bytes);
2656
2657exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302658 /* ToDo: There may be a corner case when SSR happens back to back during
2659 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302660 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302661 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302662 memset(buffer, 0, bytes);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302663 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 pthread_mutex_unlock(&in->lock);
2665
2666 if (ret != 0) {
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302667 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302668 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302669 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302670 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302671 in->standby = true;
2672 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 in_standby(&in->stream.common);
2674 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002675 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
2676 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002677 }
2678 return bytes;
2679}
2680
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302681static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682{
2683 return 0;
2684}
2685
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002686static int add_remove_audio_effect(const struct audio_stream *stream,
2687 effect_handle_t effect,
2688 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002689{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002690 struct stream_in *in = (struct stream_in *)stream;
2691 int status = 0;
2692 effect_descriptor_t desc;
2693
2694 status = (*effect)->get_descriptor(effect, &desc);
2695 if (status != 0)
2696 return status;
2697
2698 pthread_mutex_lock(&in->lock);
2699 pthread_mutex_lock(&in->dev->lock);
2700 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2701 in->enable_aec != enable &&
2702 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2703 in->enable_aec = enable;
2704 if (!in->standby)
2705 select_devices(in->dev, in->usecase);
2706 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002707 if (in->enable_ns != enable &&
2708 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2709 in->enable_ns = enable;
2710 if (!in->standby)
2711 select_devices(in->dev, in->usecase);
2712 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002713 pthread_mutex_unlock(&in->dev->lock);
2714 pthread_mutex_unlock(&in->lock);
2715
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002716 return 0;
2717}
2718
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002719static int in_add_audio_effect(const struct audio_stream *stream,
2720 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721{
Eric Laurent994a6932013-07-17 11:51:42 -07002722 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002723 return add_remove_audio_effect(stream, effect, true);
2724}
2725
2726static int in_remove_audio_effect(const struct audio_stream *stream,
2727 effect_handle_t effect)
2728{
Eric Laurent994a6932013-07-17 11:51:42 -07002729 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002730 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731}
2732
2733static int adev_open_output_stream(struct audio_hw_device *dev,
2734 audio_io_handle_t handle,
2735 audio_devices_t devices,
2736 audio_output_flags_t flags,
2737 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302738 struct audio_stream_out **stream_out,
2739 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002740{
2741 struct audio_device *adev = (struct audio_device *)dev;
2742 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002743 int i, ret = 0;
Steve Kondik5a447012014-12-02 16:04:20 -08002744 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002745
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002746 *stream_out = NULL;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302747
2748 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2749 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
2750 ALOGE(" sound card is not active rejecting compress output open request");
2751 return -EINVAL;
2752 }
2753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2755
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302756 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2757 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2758 devices, flags, &out->stream);
2759
2760
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002761 if (!out) {
2762 return -ENOMEM;
2763 }
2764
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002765 if (devices == AUDIO_DEVICE_NONE)
2766 devices = AUDIO_DEVICE_OUT_SPEAKER;
2767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002768 out->flags = flags;
2769 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002770 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002771 out->format = config->format;
2772 out->sample_rate = config->sample_rate;
2773 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2774 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002775 out->handle = handle;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002776 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002777 out->non_blocking = 0;
2778 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002779
2780 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002781 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
Mingming Yinee733602014-04-03 17:47:22 -07002782 (
2783#ifdef AFE_PROXY_ENABLED
2784 out->devices & AUDIO_DEVICE_OUT_PROXY ||
2785#endif
2786 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002787
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002788 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002789 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2790 ret = read_hdmi_channel_masks(out);
2791
Mingming Yinee733602014-04-03 17:47:22 -07002792#ifdef AFE_PROXY_ENABLED
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002793 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2794 ret = audio_extn_read_afe_proxy_channel_masks(out);
Mingming Yinee733602014-04-03 17:47:22 -07002795#endif
2796
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002797 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002798 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002799 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002800
2801 if (config->sample_rate == 0)
2802 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2803 if (config->channel_mask == 0)
2804 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2805
2806 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002807 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002808 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2809 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002810 out->config.rate = config->sample_rate;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302811 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002812 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Mingming Yinee733602014-04-03 17:47:22 -07002813#ifdef COMPRESS_VOIP_ENABLED
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002814 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2815 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002816 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002817 ret = voice_extn_compress_voip_open_output_stream(out);
2818 if (ret != 0) {
2819 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2820 __func__, ret);
2821 goto error_open;
2822 }
Mingming Yinee733602014-04-03 17:47:22 -07002823#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002824 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302825 ALOGD("%s: copl(%x): sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
2826 __func__, (unsigned int)out, config->sample_rate, config->channel_mask, devices, flags);
2827
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002828 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2829 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2830 ALOGE("%s: Unsupported Offload information", __func__);
2831 ret = -EINVAL;
2832 goto error_open;
2833 }
Mingming Yin90310102013-11-13 16:57:00 -08002834 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002835 !audio_extn_is_dolby_format(config->offload_info.format)) {
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002836 ALOGE("%s: Unsupported offload audio format %x", __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002837 ret = -EINVAL;
2838 goto error_open;
2839 }
2840
2841 out->compr_config.codec = (struct snd_codec *)
2842 calloc(1, sizeof(struct snd_codec));
2843
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002844 if (!out->compr_config.codec) {
2845 ret = -ENOMEM;
2846 goto error_open;
2847 }
2848
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002849 out->usecase = get_offload_usecase(adev);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002850 if (config->offload_info.channel_mask)
2851 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002852 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002853 out->channel_mask = config->channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002854 config->offload_info.channel_mask = config->channel_mask;
2855 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 out->format = config->offload_info.format;
2857 out->sample_rate = config->offload_info.sample_rate;
2858
2859 out->stream.set_callback = out_set_callback;
2860 out->stream.pause = out_pause;
2861 out->stream.resume = out_resume;
2862 out->stream.drain = out_drain;
2863 out->stream.flush = out_flush;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002864 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002865
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002866 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002867 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002868 audio_extn_dolby_get_snd_codec_id(adev, out,
2869 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002870 else
2871 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 get_snd_codec_id(config->offload_info.format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002873
ApurupaPattapu0c566872014-01-10 14:46:02 -08002874 if (audio_is_offload_pcm(config->offload_info.format)) {
2875 out->compr_config.fragment_size =
2876 platform_get_pcm_offload_buffer_size(&config->offload_info);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002877 } else {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002878 out->compr_config.fragment_size =
2879 platform_get_compress_offload_buffer_size(&config->offload_info);
2880 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002881 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0043e152014-10-23 14:42:59 -07002882#ifdef NEW_SAMPLE_RATE_ENABLED
2883 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
2884#else
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002885 out->compr_config.codec->sample_rate =
2886 compress_get_alsa_rate(config->offload_info.sample_rate);
Eric Laurent0043e152014-10-23 14:42:59 -07002887#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002888 out->compr_config.codec->bit_rate =
2889 config->offload_info.bit_rate;
2890 out->compr_config.codec->ch_in =
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302891 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002892 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002893 out->bit_width = config->offload_info.bit_width;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002894
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002895 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
Steve Kondik37454012014-11-23 19:54:21 -08002896 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002897 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2898 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002899
Steve Kondik3abbbc82014-11-29 14:14:43 -08002900 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002901 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002902
Steve Kondik3abbbc82014-11-29 14:14:43 -08002903 if (out->bit_width == 24)
2904 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002905
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002906#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik37454012014-11-23 19:54:21 -08002907 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
2908 out->compr_config.codec->options.flac_dec.sample_size = config->offload_info.bit_width;
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002909#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002910
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002911 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2912 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002913
Mingming Yind48310a2015-06-10 16:28:10 -07002914 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002915 //this flag is set from framework only if its for PCM formats
2916 //no need to check for PCM format again
2917 out->non_blocking = 0;
2918 out->use_small_bufs = true;
2919 ALOGI("Keep write blocking for small buff: non_blockling %d",
2920 out->non_blocking);
2921 }
2922
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002923 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002924 out->offload_state = OFFLOAD_STATE_IDLE;
2925 out->playback_started = 0;
2926
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 create_offload_callback_thread(out);
2928 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2929 __func__, config->offload_info.version,
2930 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002931 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -08002932 check_and_set_gapless_mode(adev);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002933
Mingming Yinee733602014-04-03 17:47:22 -07002934#ifdef INCALL_MUSIC_ENABLED
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002935 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2936 ret = voice_check_and_set_incall_music_usecase(adev, out);
2937 if (ret != 0) {
2938 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2939 __func__, ret);
2940 goto error_open;
2941 }
Mingming Yinee733602014-04-03 17:47:22 -07002942#endif
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302943 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2944 if (config->sample_rate == 0)
2945 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2946 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2947 config->sample_rate != 8000) {
2948 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2949 ret = -EINVAL;
2950 goto error_open;
2951 }
2952 out->sample_rate = config->sample_rate;
2953 out->config.rate = config->sample_rate;
2954 if (config->format == AUDIO_FORMAT_DEFAULT)
2955 config->format = AUDIO_FORMAT_PCM_16_BIT;
2956 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2957 config->format = AUDIO_FORMAT_PCM_16_BIT;
2958 ret = -EINVAL;
2959 goto error_open;
2960 }
2961 out->format = config->format;
2962 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2963 out->config = pcm_config_afe_proxy_playback;
2964 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002965 } else {
Steve Kondik3abbbc82014-11-29 14:14:43 -08002966#ifndef LOW_LATENCY_PRIMARY
2967 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
2968 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2969 out->config = pcm_config_low_latency;
Steve Kondikb045f472014-11-12 23:24:07 -08002970#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -08002971#ifdef LOW_LATENCY_PRIMARY
2972 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2973 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2974 out->config = pcm_config_deep_buffer;
2975#endif
2976 } else {
2977 /* primary path is the default path selected if no other outputs are available/suitable */
2978 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
2979#ifdef LOW_LATENCY_PRIMARY
2980 out->config = pcm_config_low_latency;
2981#else
2982 out->config = pcm_config_deep_buffer;
2983#endif
2984 }
2985 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2986 if (k_enable_extended_precision
2987 && pcm_params_format_test(adev->use_case_table[out->usecase],
2988 pcm_format_from_audio_format(config->format))) {
2989 out->config.format = pcm_format_from_audio_format(config->format);
2990 /* out->format already set to config->format */
2991 } else {
2992 /* deny the externally proposed config format
2993 * and use the one specified in audio_hw layer configuration.
2994 * Note: out->format is returned by out->stream.common.get_format()
2995 * and is used to set config->format in the code several lines below.
2996 */
Steve Kondik5a447012014-12-02 16:04:20 -08002997 ALOGW("Audio format %x is not available on this output", out->format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002998 out->format = audio_format_from_pcm_format(out->config.format);
2999 }
3000 }
3001
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003002 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003003 }
3004
Steve Kondik5a447012014-12-02 16:04:20 -08003005 ALOGV("%s flags %x, format %x, sample_rate %d, out->bit_width %d",
3006 __func__, flags, out->format, out->sample_rate, out->bit_width);
3007
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003008 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
Steve Kondik3abbbc82014-11-29 14:14:43 -08003009 flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003010 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003011 if(adev->primary_output == NULL)
3012 adev->primary_output = out;
3013 else {
3014 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003015 ret = -EEXIST;
3016 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003017 }
3018 }
3019
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003020 /* Check if this usecase is already existing */
3021 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella0d06c8e2014-04-17 20:00:41 -07003022 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3023 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003024 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003025 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003026 ret = -EEXIST;
3027 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003028 }
3029 pthread_mutex_unlock(&adev->lock);
3030
3031 out->stream.common.get_sample_rate = out_get_sample_rate;
3032 out->stream.common.set_sample_rate = out_set_sample_rate;
3033 out->stream.common.get_buffer_size = out_get_buffer_size;
3034 out->stream.common.get_channels = out_get_channels;
3035 out->stream.common.get_format = out_get_format;
3036 out->stream.common.set_format = out_set_format;
3037 out->stream.common.standby = out_standby;
3038 out->stream.common.dump = out_dump;
3039 out->stream.common.set_parameters = out_set_parameters;
3040 out->stream.common.get_parameters = out_get_parameters;
3041 out->stream.common.add_audio_effect = out_add_audio_effect;
3042 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3043 out->stream.get_latency = out_get_latency;
3044 out->stream.set_volume = out_set_volume;
3045 out->stream.write = out_write;
3046 out->stream.get_render_position = out_get_render_position;
3047 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003048 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003050 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003051 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003052 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003053
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303054 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
3055 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003057 config->format = out->stream.common.get_format(&out->stream.common);
3058 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3059 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3060
3061 *stream_out = &out->stream;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303062 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
3063 use_case_table[out->usecase]);
Eric Laurent994a6932013-07-17 11:51:42 -07003064 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003065 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003066
3067error_open:
3068 free(out);
3069 *stream_out = NULL;
3070 ALOGD("%s: exit: ret %d", __func__, ret);
3071 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003072}
3073
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303074static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 struct audio_stream_out *stream)
3076{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003077 struct stream_out *out = (struct stream_out *)stream;
3078 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003079 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003080
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303081 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3082
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003083 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303084 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003085 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303086 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003087 if(ret != 0)
3088 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3089 __func__, ret);
3090 }
3091 else
3092 out_standby(&stream->common);
3093
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003094 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003096 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003097 if (out->compr_config.codec != NULL)
3098 free(out->compr_config.codec);
3099 }
3100 pthread_cond_destroy(&out->cond);
3101 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003103 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104}
3105
Alexy Joseph55204352014-10-06 12:15:01 -07003106static void close_compress_sessions(struct audio_device *adev)
3107{
3108 struct stream_out *out = NULL;
3109 struct listnode *node = NULL;
3110 struct listnode *tmp = NULL;
3111 struct audio_usecase *usecase = NULL;
3112 pthread_mutex_lock(&adev->lock);
3113 list_for_each_safe(node, tmp, &adev->usecase_list) {
3114 usecase = node_to_item(node, struct audio_usecase, list);
3115 if (is_offload_usecase(usecase->id)) {
3116 if (usecase && usecase->stream.out) {
3117 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3118 out = usecase->stream.out;
3119 pthread_mutex_unlock(&adev->lock);
3120 out_standby(&out->stream.common);
3121 pthread_mutex_lock(&adev->lock);
3122 }
3123 }
3124 }
3125 pthread_mutex_unlock(&adev->lock);
3126}
3127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003128static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3129{
3130 struct audio_device *adev = (struct audio_device *)dev;
3131 struct str_parms *parms;
3132 char *str;
3133 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003134 int val;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303135 int ret;
3136 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003138 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003139 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003140
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303141 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3142 if (ret >= 0) {
3143 char *snd_card_status = value+2;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303144 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05303145 struct listnode *node;
3146 struct audio_usecase *usecase;
3147
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303148 ALOGD("Received sound card OFFLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303149 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3150
Alexy Joseph55204352014-10-06 12:15:01 -07003151 //close compress sessions on OFFLINE status
3152 close_compress_sessions(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303153 } else if (strstr(snd_card_status, "ONLINE")) {
3154 ALOGD("Received sound card ONLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303155 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303156 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303157 }
3158
3159 pthread_mutex_lock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303160 status = voice_set_parameters(adev, parms);
3161 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003162 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003163
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303164 status = platform_set_parameters(adev->platform, parms);
3165 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003166 goto done;
3167
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303168 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3169 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003170 /* When set to false, HAL should disable EC and NS
3171 * But it is currently not supported.
3172 */
3173 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3174 adev->bluetooth_nrec = true;
3175 else
3176 adev->bluetooth_nrec = false;
3177 }
3178
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303179 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3180 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003181 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3182 adev->screen_off = false;
3183 else
3184 adev->screen_off = true;
3185 }
3186
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303187 ret = str_parms_get_int(parms, "rotation", &val);
3188 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003189 bool reverse_speakers = false;
3190 switch(val) {
3191 // FIXME: note that the code below assumes that the speakers are in the correct placement
3192 // relative to the user when the device is rotated 90deg from its default rotation. This
3193 // assumption is device-specific, not platform-specific like this code.
3194 case 270:
3195 reverse_speakers = true;
3196 break;
3197 case 0:
3198 case 90:
3199 case 180:
3200 break;
3201 default:
3202 ALOGE("%s: unexpected rotation of %d", __func__, val);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303203 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003204 }
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303205 if (status == 0) {
3206 if (adev->speaker_lr_swap != reverse_speakers) {
3207 adev->speaker_lr_swap = reverse_speakers;
3208 // only update the selected device if there is active pcm playback
3209 struct audio_usecase *usecase;
3210 struct listnode *node;
3211 list_for_each(node, &adev->usecase_list) {
3212 usecase = node_to_item(node, struct audio_usecase, list);
3213 if (usecase->type == PCM_PLAYBACK) {
Steve Kondik3abbbc82014-11-29 14:14:43 -08003214 status = select_devices(adev, usecase->id);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303215 break;
3216 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003217 }
3218 }
3219 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003220 }
3221
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003222 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003223
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003224done:
3225 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003226 pthread_mutex_unlock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303227 ALOGV("%s: exit with code(%d)", __func__, status);
3228 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229}
3230
3231static char* adev_get_parameters(const struct audio_hw_device *dev,
3232 const char *keys)
3233{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003234 struct audio_device *adev = (struct audio_device *)dev;
3235 struct str_parms *reply = str_parms_create();
3236 struct str_parms *query = str_parms_create_str(keys);
3237 char *str;
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303238 char value[256] = {0};
3239 int ret = 0;
3240
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003241 if (!query || !reply) {
3242 ALOGE("adev_get_parameters: failed to create query or reply");
3243 return NULL;
3244 }
3245
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303246 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
3247 sizeof(value));
3248 if (ret >=0) {
3249 int val = 1;
3250 pthread_mutex_lock(&adev->snd_card_status.lock);
3251 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3252 val = 0;
3253 pthread_mutex_unlock(&adev->snd_card_status.lock);
3254 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, val);
3255 goto exit;
3256 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003257
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003258 pthread_mutex_lock(&adev->lock);
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303259
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003260 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003261 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003262 platform_get_parameters(adev->platform, query, reply);
Naresh Tannirucef332d2014-06-04 18:17:56 +05303263 pthread_mutex_unlock(&adev->lock);
3264
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303265exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003266 str = str_parms_to_str(reply);
3267 str_parms_destroy(query);
3268 str_parms_destroy(reply);
3269
3270 ALOGV("%s: exit: returns - %s", __func__, str);
3271 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003272}
3273
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303274static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003275{
3276 return 0;
3277}
3278
3279static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3280{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003281 int ret;
3282 struct audio_device *adev = (struct audio_device *)dev;
Eric Laurent321b96d2014-09-10 13:21:01 -05003283
3284 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3285
Haynes Mathew George5191a852013-09-11 14:19:36 -07003286 pthread_mutex_lock(&adev->lock);
3287 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003288 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003289 pthread_mutex_unlock(&adev->lock);
3290 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003291}
3292
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303293static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3294 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295{
3296 return -ENOSYS;
3297}
3298
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303299static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3300 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003301{
3302 return -ENOSYS;
3303}
3304
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303305static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3306 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003307{
3308 return -ENOSYS;
3309}
3310
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303311static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3312 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313{
3314 return -ENOSYS;
3315}
3316
3317static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3318{
3319 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320 pthread_mutex_lock(&adev->lock);
3321 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003322 ALOGD("%s mode %d\n", __func__, mode);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303323 if (amplifier_set_mode(mode) != 0)
3324 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003325 adev->mode = mode;
3326 }
3327 pthread_mutex_unlock(&adev->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003328
3329 audio_extn_extspk_set_mode(adev->extspk, mode);
3330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331 return 0;
3332}
3333
3334static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3335{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003336 int ret;
3337
3338 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003339 ALOGD("%s state %d\n", __func__, state);
Shreyas Nagasandra Chandrasekhar9781c6c2014-12-01 05:49:35 -08003340 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003341 pthread_mutex_unlock(&adev->lock);
3342
3343 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003344}
3345
3346static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3347{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003348 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003349 return 0;
3350}
3351
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303352static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353 const struct audio_config *config)
3354{
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303355 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003356
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003357 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3358 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003359}
3360
3361static int adev_open_input_stream(struct audio_hw_device *dev,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303362 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003363 audio_devices_t devices,
3364 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303365 struct audio_stream_in **stream_in,
3366 audio_input_flags_t flags __unused,
3367 const char *address __unused,
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003368 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003369{
3370 struct audio_device *adev = (struct audio_device *)dev;
3371 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003372 int ret = 0, buffer_size, frame_size;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303373 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003374 bool is_low_latency = false;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003376 *stream_in = NULL;
3377 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3378 return -EINVAL;
3379
3380 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003381
3382 if (!in) {
3383 ALOGE("failed to allocate input stream");
3384 return -ENOMEM;
3385 }
3386
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303387 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003388 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3389 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003391 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
3392
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 in->stream.common.get_sample_rate = in_get_sample_rate;
3394 in->stream.common.set_sample_rate = in_set_sample_rate;
3395 in->stream.common.get_buffer_size = in_get_buffer_size;
3396 in->stream.common.get_channels = in_get_channels;
3397 in->stream.common.get_format = in_get_format;
3398 in->stream.common.set_format = in_set_format;
3399 in->stream.common.standby = in_standby;
3400 in->stream.common.dump = in_dump;
3401 in->stream.common.set_parameters = in_set_parameters;
3402 in->stream.common.get_parameters = in_get_parameters;
3403 in->stream.common.add_audio_effect = in_add_audio_effect;
3404 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3405 in->stream.set_gain = in_set_gain;
3406 in->stream.read = in_read;
3407 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3408
3409 in->device = devices;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003410 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 in->standby = 1;
3413 in->channel_mask = config->channel_mask;
3414
3415 /* Update config params with the requested sample rate and channels */
3416 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003417 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3418 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3419 is_low_latency = true;
3420#if LOW_LATENCY_CAPTURE_USE_CASE
3421 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3422#endif
3423 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003424 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003425 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003426 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303428 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkala3c0036d2014-12-17 16:45:10 +05303429 if (adev->mode != AUDIO_MODE_IN_CALL) {
3430 ret = -EINVAL;
3431 goto err_open;
Pavan Chikkala3ec42ef2014-11-21 20:57:48 +05303432 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303433 if (config->sample_rate == 0)
3434 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3435 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3436 config->sample_rate != 8000) {
3437 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3438 ret = -EINVAL;
3439 goto err_open;
3440 }
3441 if (config->format == AUDIO_FORMAT_DEFAULT)
3442 config->format = AUDIO_FORMAT_PCM_16_BIT;
3443 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3444 config->format = AUDIO_FORMAT_PCM_16_BIT;
3445 ret = -EINVAL;
3446 goto err_open;
3447 }
3448 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3449 in->config = pcm_config_afe_proxy_record;
3450 in->config.channels = channel_count;
3451 in->config.rate = config->sample_rate;
3452 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003453 if(audio_extn_ssr_get_enabled()) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303454 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003455 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3456 ret = -EINVAL;
3457 goto err_open;
3458 }
3459 } else {
Mingming Yindaf9c542014-09-16 17:41:33 -07003460 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003461 }
Mingming Yine62d7842013-10-25 16:26:03 -07003462 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08003463 audio_extn_compr_cap_format_supported(config->format) &&
3464 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303465 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003466 } else {
3467 in->config.channels = channel_count;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303468 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003469 buffer_size = get_input_buffer_size(config->sample_rate,
3470 config->format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003471 channel_count,
3472 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003473 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003474 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3475 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3476 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3477 (in->config.rate == 8000 || in->config.rate == 16000) &&
3478 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3479 voice_extn_compress_voip_open_input_stream(in);
3480 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003481 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482
3483 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003484 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003485 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003486
3487err_open:
3488 free(in);
3489 *stream_in = NULL;
3490 return ret;
3491}
3492
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303493static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494 struct audio_stream_in *stream)
3495{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003496 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003497 struct stream_in *in = (struct stream_in *)stream;
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303498 struct audio_device *adev = in->dev;
3499
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303500 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003501
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003502 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303503 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003504 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303505 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003506 if (ret != 0)
3507 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3508 __func__, ret);
3509 } else
3510 in_standby(&stream->common);
3511
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303512 if (audio_extn_ssr_get_enabled() &&
3513 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003514 audio_extn_ssr_deinit();
3515 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003516 free(stream);
3517
Mingming Yine62d7842013-10-25 16:26:03 -07003518 if(audio_extn_compr_cap_enabled() &&
3519 audio_extn_compr_cap_format_supported(in->config.format))
3520 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003521 return;
3522}
3523
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303524static int adev_dump(const audio_hw_device_t *device __unused,
3525 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003526{
3527 return 0;
3528}
3529
Steve Kondik3abbbc82014-11-29 14:14:43 -08003530/* verifies input and output devices and their capabilities.
3531 *
3532 * This verification is required when enabling extended bit-depth or
3533 * sampling rates, as not all qcom products support it.
3534 *
3535 * Suitable for calling only on initialization such as adev_open().
3536 * It fills the audio_device use_case_table[] array.
3537 *
3538 * Has a side-effect that it needs to configure audio routing / devices
3539 * in order to power up the devices and read the device parameters.
3540 * It does not acquire any hw device lock. Should restore the devices
3541 * back to "normal state" upon completion.
3542 */
3543static int adev_verify_devices(struct audio_device *adev)
3544{
3545 /* enumeration is a bit difficult because one really wants to pull
3546 * the use_case, device id, etc from the hidden pcm_device_table[].
3547 * In this case there are the following use cases and device ids.
3548 *
3549 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3550 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3551 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3552 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3553 * [USECASE_AUDIO_RECORD] = {0, 0},
3554 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3555 * [USECASE_VOICE_CALL] = {2, 2},
3556 *
3557 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3558 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3559 */
3560
3561 /* should be the usecases enabled in adev_open_input_stream() */
3562 static const int test_in_usecases[] = {
3563 USECASE_AUDIO_RECORD,
3564 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3565 };
3566 /* should be the usecases enabled in adev_open_output_stream()*/
3567 static const int test_out_usecases[] = {
3568 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3569 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3570 };
3571 static const usecase_type_t usecase_type_by_dir[] = {
3572 PCM_PLAYBACK,
3573 PCM_CAPTURE,
3574 };
3575 static const unsigned flags_by_dir[] = {
3576 PCM_OUT,
3577 PCM_IN,
3578 };
3579
3580 size_t i;
3581 unsigned dir;
3582 const unsigned card_id = adev->snd_card;
3583 char info[512]; /* for possible debug info */
3584
3585 for (dir = 0; dir < 2; ++dir) {
3586 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3587 const unsigned flags_dir = flags_by_dir[dir];
3588 const size_t testsize =
3589 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3590 const int *testcases =
3591 dir ? test_in_usecases : test_out_usecases;
3592 const audio_devices_t audio_device =
3593 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3594
3595 for (i = 0; i < testsize; ++i) {
3596 const audio_usecase_t audio_usecase = testcases[i];
3597 int device_id;
3598 snd_device_t snd_device;
3599 struct pcm_params **pparams;
3600 struct stream_out out;
3601 struct stream_in in;
3602 struct audio_usecase uc_info;
3603 int retval;
3604
3605 pparams = &adev->use_case_table[audio_usecase];
3606 pcm_params_free(*pparams); /* can accept null input */
3607 *pparams = NULL;
3608
3609 /* find the device ID for the use case (signed, for error) */
3610 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3611 if (device_id < 0)
3612 continue;
3613
3614 /* prepare structures for device probing */
3615 memset(&uc_info, 0, sizeof(uc_info));
3616 uc_info.id = audio_usecase;
3617 uc_info.type = usecase_type;
3618 if (dir) {
3619 adev->active_input = &in;
3620 memset(&in, 0, sizeof(in));
3621 in.device = audio_device;
3622 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3623 uc_info.stream.in = &in;
3624 } else {
3625 adev->active_input = NULL;
3626 }
3627 memset(&out, 0, sizeof(out));
3628 out.devices = audio_device; /* only field needed in select_devices */
3629 uc_info.stream.out = &out;
3630 uc_info.devices = audio_device;
3631 uc_info.in_snd_device = SND_DEVICE_NONE;
3632 uc_info.out_snd_device = SND_DEVICE_NONE;
3633 list_add_tail(&adev->usecase_list, &uc_info.list);
3634
3635 /* select device - similar to start_(in/out)put_stream() */
3636 retval = select_devices(adev, audio_usecase);
3637 if (retval >= 0) {
3638 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3639#if LOG_NDEBUG == 0
3640 if (*pparams) {
3641 ALOGV("%s: (%s) card %d device %d", __func__,
3642 dir ? "input" : "output", card_id, device_id);
3643 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
3644 ALOGV(info); /* print parameters */
3645 } else {
3646 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3647 }
3648#endif
3649 }
3650
3651 /* deselect device - similar to stop_(in/out)put_stream() */
3652 /* 1. Get and set stream specific mixer controls */
3653 retval = disable_audio_route(adev, &uc_info);
3654 /* 2. Disable the rx device */
3655 retval = disable_snd_device(adev,
3656 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
3657 list_remove(&uc_info.list);
3658 }
3659 }
3660 adev->active_input = NULL; /* restore adev state */
3661 return 0;
3662}
3663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664static int adev_close(hw_device_t *device)
3665{
Steve Kondik3abbbc82014-11-29 14:14:43 -08003666 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003667 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003668
3669 if (!adev)
3670 return 0;
3671
3672 pthread_mutex_lock(&adev_init_lock);
3673
3674 if ((--audio_device_ref_count) == 0) {
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303675 if (amplifier_close() != 0)
3676 ALOGE("Amplifier close failed");
Kiran Kandide144c82013-11-20 15:58:32 -08003677 audio_extn_listen_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07003678 audio_route_free(adev->audio_route);
3679 free(adev->snd_dev_ref_cnt);
3680 platform_deinit(adev->platform);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003681 audio_extn_extspk_deinit(adev->extspk);
Steve Kondik3abbbc82014-11-29 14:14:43 -08003682 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3683 pcm_params_free(adev->use_case_table[i]);
3684 }
Kiran Kandi910e1862013-10-29 13:29:42 -07003685 free(device);
3686 adev = NULL;
3687 }
3688 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 return 0;
3690}
3691
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003692/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3693 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3694 * just that it _might_ work.
3695 */
3696static int period_size_is_plausible_for_low_latency(int period_size)
3697{
3698 switch (period_size) {
3699 case 160:
3700 case 240:
3701 case 320:
3702 case 480:
3703 return 1;
3704 default:
3705 return 0;
3706 }
3707}
3708
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709static int adev_open(const hw_module_t *module, const char *name,
3710 hw_device_t **device)
3711{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003712 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003713
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003714 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3716
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003717 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003718 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003719 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003720 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003721 ALOGD("%s: returning existing instance of adev", __func__);
3722 ALOGD("%s: exit", __func__);
3723 pthread_mutex_unlock(&adev_init_lock);
3724 return 0;
3725 }
3726
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 adev = calloc(1, sizeof(struct audio_device));
3728
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003729 if (!adev) {
3730 pthread_mutex_unlock(&adev_init_lock);
3731 return -ENOMEM;
3732 }
3733
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003734 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3737 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3738 adev->device.common.module = (struct hw_module_t *)module;
3739 adev->device.common.close = adev_close;
3740
3741 adev->device.init_check = adev_init_check;
3742 adev->device.set_voice_volume = adev_set_voice_volume;
3743 adev->device.set_master_volume = adev_set_master_volume;
3744 adev->device.get_master_volume = adev_get_master_volume;
3745 adev->device.set_master_mute = adev_set_master_mute;
3746 adev->device.get_master_mute = adev_get_master_mute;
3747 adev->device.set_mode = adev_set_mode;
3748 adev->device.set_mic_mute = adev_set_mic_mute;
3749 adev->device.get_mic_mute = adev_get_mic_mute;
3750 adev->device.set_parameters = adev_set_parameters;
3751 adev->device.get_parameters = adev_get_parameters;
3752 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3753 adev->device.open_output_stream = adev_open_output_stream;
3754 adev->device.close_output_stream = adev_close_output_stream;
3755 adev->device.open_input_stream = adev_open_input_stream;
3756 adev->device.close_input_stream = adev_close_input_stream;
3757 adev->device.dump = adev_dump;
3758
3759 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003761 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003762 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003765 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003766 /* adev->cur_hdmi_channels = 0; by calloc() */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08003767 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3768 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003769 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003770 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003771 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly9b7e96b2014-02-14 14:45:49 -08003772 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003773 adev->offload_usecases_state = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003774
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303775 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3776 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
3777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003778 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003779 adev->platform = platform_init(adev);
3780 if (!adev->platform) {
3781 free(adev->snd_dev_ref_cnt);
3782 free(adev);
3783 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3784 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003785 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003786 return -EINVAL;
3787 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003788
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303789 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
Eric Laurentda46bfb2014-08-25 22:39:29 -05003790 adev->extspk = audio_extn_extspk_init(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303791
Eric Laurentc4aef752013-09-12 17:45:53 -07003792 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3793 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3794 if (adev->visualizer_lib == NULL) {
3795 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3796 } else {
3797 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3798 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003799 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003800 "visualizer_hal_start_output");
3801 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003802 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003803 "visualizer_hal_stop_output");
3804 }
3805 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003806 audio_extn_listen_init(adev, adev->snd_card);
Eric Laurentc4aef752013-09-12 17:45:53 -07003807
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003808 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3809 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3810 if (adev->offload_effects_lib == NULL) {
3811 ALOGE("%s: DLOPEN failed for %s", __func__,
3812 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3813 } else {
3814 ALOGV("%s: DLOPEN successful for %s", __func__,
3815 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3816 adev->offload_effects_start_output =
3817 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3818 "offload_effects_bundle_hal_start_output");
3819 adev->offload_effects_stop_output =
3820 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3821 "offload_effects_bundle_hal_stop_output");
3822 }
3823 }
3824
Dan Pasanend4c2ca92015-08-10 19:47:43 -05003825 if (amplifier_open() != 0)
3826 ALOGE("Amplifier initialization failed");
3827
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828 *device = &adev->device.common;
Steve Kondik3abbbc82014-11-29 14:14:43 -08003829 if (k_enable_extended_precision)
3830 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003831
Kiran Kandi910e1862013-10-29 13:29:42 -07003832 audio_device_ref_count++;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003833
3834 char value[PROPERTY_VALUE_MAX];
3835 int trial;
3836 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3837 trial = atoi(value);
3838 if (period_size_is_plausible_for_low_latency(trial)) {
3839 pcm_config_low_latency.period_size = trial;
3840 pcm_config_low_latency.start_threshold = trial / 4;
3841 pcm_config_low_latency.avail_min = trial / 4;
3842 configured_low_latency_capture_period_size = trial;
3843 }
3844 }
3845 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3846 trial = atoi(value);
3847 if (period_size_is_plausible_for_low_latency(trial)) {
3848 configured_low_latency_capture_period_size = trial;
3849 }
3850 }
3851
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003852 pthread_mutex_unlock(&adev_init_lock);
3853
Eric Laurent994a6932013-07-17 11:51:42 -07003854 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003855 return 0;
3856}
3857
3858static struct hw_module_methods_t hal_module_methods = {
3859 .open = adev_open,
3860};
3861
3862struct audio_module HAL_MODULE_INFO_SYM = {
3863 .common = {
3864 .tag = HARDWARE_MODULE_TAG,
3865 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3866 .hal_api_version = HARDWARE_HAL_API_VERSION,
3867 .id = AUDIO_HARDWARE_MODULE_ID,
3868 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003869 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003870 .methods = &hal_module_methods,
3871 },
3872};