blob: 1f9b63f10f261cc6408eeff072bec5a9bfe46912 [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,
Eric Laurent86659ab2015-07-06 17:54:15 -0700116 .stop_threshold = INT_MAX,
117 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700118};
119
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530120#define AFE_PROXY_CHANNEL_COUNT 2
121#define AFE_PROXY_SAMPLING_RATE 48000
122
123#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
124#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
125
126struct pcm_config pcm_config_afe_proxy_playback = {
127 .channels = AFE_PROXY_CHANNEL_COUNT,
128 .rate = AFE_PROXY_SAMPLING_RATE,
129 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
130 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
131 .format = PCM_FORMAT_S16_LE,
132 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
133 .stop_threshold = INT_MAX,
134 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
135};
136
137#define AFE_PROXY_RECORD_PERIOD_SIZE 768
138#define AFE_PROXY_RECORD_PERIOD_COUNT 4
139
140struct pcm_config pcm_config_afe_proxy_record = {
141 .channels = AFE_PROXY_CHANNEL_COUNT,
142 .rate = AFE_PROXY_SAMPLING_RATE,
143 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
144 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
145 .format = PCM_FORMAT_S16_LE,
146 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
147 .stop_threshold = INT_MAX,
148 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
149};
150
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800151const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700152 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
153 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
154 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700155 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700156#ifdef MULTIPLE_OFFLOAD_ENABLED
157 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
158 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
159 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
160 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
161 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
162 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
163 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
164 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
165#endif
vivek mehtac2711cd2015-08-26 14:01:20 -0700166 [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] = "compress-offload-playback2",
Ravi Kumar Alamanda8c884872015-06-25 20:08:01 -0700167 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700168 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700169 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700170 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700171 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700172 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800173 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800174 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700175 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yinee733602014-04-03 17:47:22 -0700176
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700177 [USECASE_VOICE2_CALL] = "voice2-call",
178 [USECASE_VOLTE_CALL] = "volte-call",
179 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat111aeb32014-02-12 17:58:59 -0800180 [USECASE_VOWLAN_CALL] = "vowlan-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800181 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700182 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
183 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
184 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800185 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
186 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
187 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
188
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700189 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
190 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700191 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
192 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530193
194 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
195 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700196};
197
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700198static const audio_usecase_t offload_usecases[] = {
199 USECASE_AUDIO_PLAYBACK_OFFLOAD,
200#ifdef MULTIPLE_OFFLOAD_ENABLED
201 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
202 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
Steve Kondikac72feb2014-07-20 23:15:34 -0700203#ifndef PLATFORM_MSM8974
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700204 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
205 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
206 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
207 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
Steve Kondikac72feb2014-07-20 23:15:34 -0700208#endif
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700209 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
Steve Kondikac72feb2014-07-20 23:15:34 -0700210#ifndef PLATFORM_MSM8974
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700211 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
212#endif
Steve Kondikac72feb2014-07-20 23:15:34 -0700213#endif
vivek mehtac2711cd2015-08-26 14:01:20 -0700214 USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700215};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800216
217#define STRING_TO_ENUM(string) { #string, string }
218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800219struct string_to_enum {
220 const char *name;
221 uint32_t value;
222};
223
224static const struct string_to_enum out_channels_name_to_enum_table[] = {
225 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
226 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
227 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
228};
229
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700230static struct audio_device *adev = NULL;
231static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700232static unsigned int audio_device_ref_count;
233
Haynes Mathew George5191a852013-09-11 14:19:36 -0700234static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800235
Ethan Chen79c356c2015-06-07 12:26:14 -0700236static amplifier_device_t * get_amplifier_device(void)
237{
Dan Pasanen46f76f52015-08-10 19:55:39 -0500238 if (adev)
239 return adev->amp;
240
241 return NULL;
242}
243
244static int amplifier_open(void)
245{
Ethan Chen79c356c2015-06-07 12:26:14 -0700246 int rc;
247 amplifier_module_t *module;
248
Ethan Chen79c356c2015-06-07 12:26:14 -0700249 rc = hw_get_module(AMPLIFIER_HARDWARE_MODULE_ID,
250 (const hw_module_t **) &module);
251 if (rc) {
252 ALOGV("%s: Failed to obtain reference to amplifier module: %s\n",
253 __func__, strerror(-rc));
Dan Pasanen46f76f52015-08-10 19:55:39 -0500254 return -ENODEV;
Ethan Chen79c356c2015-06-07 12:26:14 -0700255 }
256
257 rc = amplifier_device_open((const hw_module_t *) module, &adev->amp);
258 if (rc) {
259 ALOGV("%s: Failed to open amplifier hardware device: %s\n",
260 __func__, strerror(-rc));
Ethan Chen79c356c2015-06-07 12:26:14 -0700261 return -ENODEV;
262 }
263
264 return 0;
265}
266
267static int amplifier_set_input_devices(uint32_t devices)
268{
269 amplifier_device_t *amp = get_amplifier_device();
270 if (amp && amp->set_input_devices)
271 return amp->set_input_devices(amp, devices);
272
273 return 0;
274}
275
276static int amplifier_set_output_devices(uint32_t devices)
277{
278 amplifier_device_t *amp = get_amplifier_device();
279 if (amp && amp->set_output_devices)
280 return amp->set_output_devices(amp, devices);
281
282 return 0;
283}
284
Ethan Chen6720ae62015-07-03 21:35:30 -0700285static int amplifier_enable_devices(uint32_t devices, bool enable)
286{
287 amplifier_device_t *amp = get_amplifier_device();
288 bool is_output = devices > SND_DEVICE_OUT_BEGIN &&
289 devices < SND_DEVICE_OUT_END;
290
291 if (amp && amp->enable_output_devices && is_output)
292 return amp->enable_output_devices(amp, devices, enable);
293
294 if (amp && amp->enable_input_devices && !is_output)
295 return amp->enable_input_devices(amp, devices, enable);
296
297 return 0;
298}
299
Ethan Chen79c356c2015-06-07 12:26:14 -0700300static int amplifier_set_mode(audio_mode_t mode)
301{
302 amplifier_device_t *amp = get_amplifier_device();
303 if (amp && amp->set_mode)
304 return amp->set_mode(amp, mode);
305
306 return 0;
307}
308
309static int amplifier_output_stream_start(struct audio_stream_out *stream,
310 bool offload)
311{
312 amplifier_device_t *amp = get_amplifier_device();
313 if (amp && amp->output_stream_start)
314 return amp->output_stream_start(amp, stream, offload);
315
316 return 0;
317}
318
319static int amplifier_input_stream_start(struct audio_stream_in *stream)
320{
321 amplifier_device_t *amp = get_amplifier_device();
322 if (amp && amp->input_stream_start)
323 return amp->input_stream_start(amp, stream);
324
325 return 0;
326}
327
328static int amplifier_output_stream_standby(struct audio_stream_out *stream)
329{
330 amplifier_device_t *amp = get_amplifier_device();
331 if (amp && amp->output_stream_standby)
332 return amp->output_stream_standby(amp, stream);
333
334 return 0;
335}
336
337static int amplifier_input_stream_standby(struct audio_stream_in *stream)
338{
339 amplifier_device_t *amp = get_amplifier_device();
340 if (amp && amp->input_stream_standby)
341 return amp->input_stream_standby(amp, stream);
342
343 return 0;
344}
345
346static int amplifier_close(void)
347{
348 amplifier_device_t *amp = get_amplifier_device();
349 if (amp)
350 amplifier_device_close(amp);
351
352 return 0;
353}
354
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800355static int check_and_set_gapless_mode(struct audio_device *adev) {
356
357
358 char value[PROPERTY_VALUE_MAX] = {0};
359 bool gapless_enabled = false;
360 const char *mixer_ctl_name = "Compress Gapless Playback";
361 struct mixer_ctl *ctl;
362
363 ALOGV("%s:", __func__);
364 property_get("audio.offload.gapless.enabled", value, NULL);
365 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
366
367 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
368 if (!ctl) {
369 ALOGE("%s: Could not get ctl for mixer cmd - %s",
370 __func__, mixer_ctl_name);
371 return -EINVAL;
372 }
373
374 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
375 ALOGE("%s: Could not set gapless mode %d",
376 __func__, gapless_enabled);
377 return -EINVAL;
378 }
379 return 0;
380}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700381
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700382static bool is_supported_format(audio_format_t format)
383{
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800384 switch (format) {
Steve Kondik3abbbc82014-11-29 14:14:43 -0800385 case AUDIO_FORMAT_MP3:
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800386 case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
387 case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
vivek mehtac2711cd2015-08-26 14:01:20 -0700388 case AUDIO_FORMAT_PCM_16_BIT:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700389#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik3abbbc82014-11-29 14:14:43 -0800390 case AUDIO_FORMAT_FLAC:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700391#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -0800392#ifdef WMA_OFFLOAD_ENABLED
393 case AUDIO_FORMAT_WMA:
394 case AUDIO_FORMAT_WMA_PRO:
395#endif
396#ifdef MP2_OFFLOAD_ENABLED
397 case AUDIO_FORMAT_MP2:
398#endif
399 case AUDIO_FORMAT_AAC_LC:
400 case AUDIO_FORMAT_AAC_HE_V1:
401 case AUDIO_FORMAT_AAC_HE_V2:
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530402 return true;
Steve Kondik3abbbc82014-11-29 14:14:43 -0800403
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800404 default:
405 return false;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530406 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700407 return false;
408}
409
410static int get_snd_codec_id(audio_format_t format)
411{
412 int id = 0;
413
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530414 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700415 case AUDIO_FORMAT_MP3:
416 id = SND_AUDIOCODEC_MP3;
417 break;
418 case AUDIO_FORMAT_AAC:
419 id = SND_AUDIOCODEC_AAC;
420 break;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530421 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehtac2711cd2015-08-26 14:01:20 -0700422 case AUDIO_FORMAT_PCM:
ApurupaPattapu0c566872014-01-10 14:46:02 -0800423 id = SND_AUDIOCODEC_PCM;
424 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700425#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800426 case AUDIO_FORMAT_FLAC:
427 id = SND_AUDIOCODEC_FLAC;
428 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700429#endif
Ethan Chenc856d972014-07-25 14:57:15 -0700430#ifdef WMA_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700431 case AUDIO_FORMAT_WMA:
432 id = SND_AUDIOCODEC_WMA;
433 break;
434 case AUDIO_FORMAT_WMA_PRO:
435 id = SND_AUDIOCODEC_WMA_PRO;
436 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700437#endif
438#ifdef MP2_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700439 case AUDIO_FORMAT_MP2:
440 id = SND_AUDIOCODEC_MP2;
441 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700442#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700443 default:
Mingming Yin90310102013-11-13 16:57:00 -0800444 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700445 }
446
447 return id;
448}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800449
Avinash Vaish8005dc82014-07-24 15:36:33 +0530450static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
451 struct audio_usecase *uc_info)
452{
453 struct listnode *node;
454 struct audio_usecase *usecase;
455
456 if (uc_info == NULL)
457 return -EINVAL;
458
459 /* Re-route all voice usecases on the shared backend other than the
460 specified usecase to new snd devices */
461 list_for_each(node, &adev->usecase_list) {
462 usecase = node_to_item(node, struct audio_usecase, list);
463 if ((usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) &&
464 (usecase != uc_info))
465 enable_audio_route(adev, usecase);
466 }
467 return 0;
468}
469
Venkata Narendra Kumar Guttac9e9e2c2014-07-09 16:29:28 +0530470int get_snd_card_state(struct audio_device *adev)
Naresh Tannirucef332d2014-06-04 18:17:56 +0530471{
472 int snd_scard_state;
473
474 if (!adev)
475 return SND_CARD_STATE_OFFLINE;
476
477 pthread_mutex_lock(&adev->snd_card_status.lock);
478 snd_scard_state = adev->snd_card_status.state;
479 pthread_mutex_unlock(&adev->snd_card_status.lock);
480
481 return snd_scard_state;
482}
483
484static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
485{
486 if (!adev)
487 return -ENOSYS;
488
489 pthread_mutex_lock(&adev->snd_card_status.lock);
490 adev->snd_card_status.state = snd_scard_state;
491 pthread_mutex_unlock(&adev->snd_card_status.lock);
492
493 return 0;
494}
495
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -0700496int pcm_ioctl(struct pcm *pcm, int request, ...)
497{
498 va_list ap;
499 void * arg;
500 int pcm_fd = *(int*)pcm;
501
502 va_start(ap, request);
503 arg = va_arg(ap, void *);
504 va_end(ap);
505
506 return ioctl(pcm_fd, request, arg);
507}
508
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700509int enable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700510 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800511{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700512 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700513 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800514
515 if (usecase == NULL)
516 return -EINVAL;
517
518 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
519
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800520 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700521 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800522 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700523 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800524
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -0800525#ifdef DS1_DOLBY_DAP_ENABLED
526 audio_extn_dolby_set_dmid(adev);
527 audio_extn_dolby_set_endpoint(adev);
528#endif
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800529 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700530 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700531 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
532 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800533 ALOGV("%s: exit", __func__);
534 return 0;
535}
536
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700537int disable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700538 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800539{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700540 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700541 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800542
543 if (usecase == NULL)
544 return -EINVAL;
545
546 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700547 if (usecase->type == PCM_CAPTURE)
548 snd_device = usecase->in_snd_device;
549 else
550 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800551 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700552 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700553 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
554 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800555 ALOGV("%s: exit", __func__);
556 return 0;
557}
558
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700559int enable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700560 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800561{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700562 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
563
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800564 if (snd_device < SND_DEVICE_MIN ||
565 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800566 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800567 return -EINVAL;
568 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700569
570 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700571
572 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
573 ALOGE("%s: Invalid sound device returned", __func__);
574 return -EINVAL;
575 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700576 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700577 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700578 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700579 return 0;
580 }
581
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700582 /* start usb playback thread */
583 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
584 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
585 audio_extn_usb_start_playback(adev);
586
587 /* start usb capture thread */
588 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
589 audio_extn_usb_start_capture(adev);
590
Tony Layher692f19a2015-01-03 13:16:45 -0500591 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
592 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700593 audio_extn_spkr_prot_is_enabled()) {
594 if (audio_extn_spkr_prot_start_processing(snd_device)) {
595 ALOGE("%s: spkr_start_processing failed", __func__);
596 return -EINVAL;
597 }
598 } else {
599 ALOGV("%s: snd_device(%d: %s)", __func__,
Steve Kondik0d268002015-10-16 01:57:18 -0700600 snd_device, device_name);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700601 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
602 adev->snd_dev_ref_cnt[snd_device]--;
603 return -EINVAL;
604 }
Steve Kondikad1a08a2015-11-11 16:26:25 +0100605 audio_extn_listen_update_status(snd_device,
606 LISTEN_EVENT_SND_DEVICE_BUSY);
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 Kondikad1a08a2015-11-11 16:26:25 +0100656 audio_extn_listen_update_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 &&
Narsinga Rao Chella2ae232a2015-07-08 19:38:38 -0700769 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
770 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
771 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700772 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
773 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700774 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700775 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700776 switch_device[usecase->id] = true;
777 num_uc_to_switch++;
778 }
779 }
780
781 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700782 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700783
784 list_for_each(node, &adev->usecase_list) {
785 usecase = node_to_item(node, struct audio_usecase, list);
786 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700787 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800788 }
789 }
790
791 list_for_each(node, &adev->usecase_list) {
792 usecase = node_to_item(node, struct audio_usecase, list);
793 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700794 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700795 }
796 }
797
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700798 /* Re-route all the usecases on the shared backend other than the
799 specified usecase to new snd devices */
800 list_for_each(node, &adev->usecase_list) {
801 usecase = node_to_item(node, struct audio_usecase, list);
802 /* Update the in_snd_device only before enabling the audio route */
803 if (switch_device[usecase->id] ) {
804 usecase->in_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530805 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
806 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700807 }
808 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700809 }
810}
811
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800812/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700813static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800814{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700815 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700816 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800817
818 switch (channels) {
819 /*
820 * Do not handle stereo output in Multi-channel cases
821 * Stereo case is handled in normal playback path
822 */
823 case 6:
824 ALOGV("%s: HDMI supports 5.1", __func__);
825 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
826 break;
827 case 8:
828 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
829 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
830 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
831 break;
832 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700833 ALOGE("HDMI does not support multi channel playback");
834 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800835 break;
836 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700837 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800838}
839
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700840static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
841{
842 struct audio_usecase *usecase;
843 struct listnode *node;
844
845 list_for_each(node, &adev->usecase_list) {
846 usecase = node_to_item(node, struct audio_usecase, list);
847 if (usecase->type == VOICE_CALL) {
848 ALOGV("%s: usecase id %d", __func__, usecase->id);
849 return usecase->id;
850 }
851 }
852 return USECASE_INVALID;
853}
854
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700855struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700856 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700857{
858 struct audio_usecase *usecase;
859 struct listnode *node;
860
861 list_for_each(node, &adev->usecase_list) {
862 usecase = node_to_item(node, struct audio_usecase, list);
863 if (usecase->id == uc_id)
864 return usecase;
865 }
866 return NULL;
867}
868
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700869int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800870{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800871 snd_device_t out_snd_device = SND_DEVICE_NONE;
872 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700873 struct audio_usecase *usecase = NULL;
874 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800875 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800876 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800877 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800878 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700879 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800880
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 usecase = get_usecase_from_list(adev, uc_id);
882 if (usecase == NULL) {
883 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
884 return -EINVAL;
885 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800886
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800887 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800888 (usecase->type == VOIP_CALL) ||
889 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700890 out_snd_device = platform_get_output_snd_device(adev->platform,
891 usecase->stream.out->devices);
892 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700893 usecase->devices = usecase->stream.out->devices;
894 } else {
895 /*
896 * If the voice call is active, use the sound devices of voice call usecase
897 * so that it would not result any device switch. All the usecases will
898 * be switched to new device when select_devices() is called for voice call
899 * usecase. This is to avoid switching devices for voice call when
900 * check_usecases_codec_backend() is called below.
901 */
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -0700902 if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700903 vc_usecase = get_usecase_from_list(adev,
904 get_voice_usecase_id_from_list(adev));
Mingming Yin6c23f382014-08-14 00:00:51 -0700905 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
906 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700907 in_snd_device = vc_usecase->in_snd_device;
908 out_snd_device = vc_usecase->out_snd_device;
909 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800910 } else if (voice_extn_compress_voip_is_active(adev)) {
911 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin6c23f382014-08-14 00:00:51 -0700912 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish6a4c3372014-06-25 12:20:37 +0530913 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin6c23f382014-08-14 00:00:51 -0700914 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800915 in_snd_device = voip_usecase->in_snd_device;
916 out_snd_device = voip_usecase->out_snd_device;
917 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800918 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800919 hfp_ucid = audio_extn_hfp_get_usecase();
920 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin6c23f382014-08-14 00:00:51 -0700921 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800922 in_snd_device = hfp_usecase->in_snd_device;
923 out_snd_device = hfp_usecase->out_snd_device;
924 }
Vimal Puthanveed8fa9eab2014-01-07 16:47:47 -0800925 } else if (audio_extn_hfp_is_active(adev)) {
926 hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
927 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
928 in_snd_device = hfp_usecase->in_snd_device;
929 out_snd_device = hfp_usecase->out_snd_device;
930 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700931 }
932 if (usecase->type == PCM_PLAYBACK) {
933 usecase->devices = usecase->stream.out->devices;
934 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700935 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700936 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700937 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700938 if (usecase->stream.out == adev->primary_output &&
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530939 adev->active_input ) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700940 select_devices(adev, adev->active_input->usecase);
941 }
942 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700943 } else if (usecase->type == PCM_CAPTURE) {
944 usecase->devices = usecase->stream.in->device;
945 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700946 if (in_snd_device == SND_DEVICE_NONE) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530947 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530948 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 -0700949 adev->primary_output && !adev->primary_output->standby) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530950 out_device = adev->primary_output->devices;
951 } else if(usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
952 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700953 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530954 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700955 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700956 }
957 }
958
959 if (out_snd_device == usecase->out_snd_device &&
960 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800961 return 0;
962 }
963
sangwoobc677242013-08-08 16:53:43 +0900964 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700965 out_snd_device, platform_get_snd_device_name(out_snd_device),
966 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800967
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800968 /*
969 * Limitation: While in call, to do a device switch we need to disable
970 * and enable both RX and TX devices though one of them is same as current
971 * device.
972 */
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800973 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700974 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800975 }
976
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700977 /* Disable current sound devices */
978 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700979 disable_audio_route(adev, usecase);
980 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800981 }
982
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700983 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700984 disable_audio_route(adev, usecase);
985 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800986 }
987
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700988 /* Enable new sound devices */
989 if (out_snd_device != SND_DEVICE_NONE) {
990 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
991 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700992 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800993 }
994
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700995 if (in_snd_device != SND_DEVICE_NONE) {
996 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700997 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700998 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700999
Avinash Vaish8005dc82014-07-24 15:36:33 +05301000 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001001 status = platform_switch_voice_call_device_post(adev->platform,
1002 out_snd_device,
1003 in_snd_device);
Avinash Vaish8005dc82014-07-24 15:36:33 +05301004 enable_audio_route_for_voice_usecases(adev, usecase);
1005 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001006
sangwoo170731f2013-06-08 15:36:36 +09001007 usecase->in_snd_device = in_snd_device;
1008 usecase->out_snd_device = out_snd_device;
1009
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001010 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001011
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301012 /* Rely on amplifier_set_devices to distinguish between in/out devices */
Ethan Chen79c356c2015-06-07 12:26:14 -07001013 amplifier_set_input_devices(in_snd_device);
1014 amplifier_set_output_devices(out_snd_device);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301015
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001016 /* Applicable only on the targets that has external modem.
1017 * Enable device command should be sent to modem only after
1018 * enabling voice call mixer controls
1019 */
1020 if (usecase->type == VOICE_CALL)
1021 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1022 out_snd_device,
1023 in_snd_device);
1024
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301025 ALOGD("%s: done",__func__);
1026
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001027 return status;
1028}
1029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001030static int stop_input_stream(struct stream_in *in)
1031{
1032 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001033 struct audio_usecase *uc_info;
1034 struct audio_device *adev = in->dev;
1035
Eric Laurentc8400632013-02-14 19:04:54 -08001036 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001037
Eric Laurent994a6932013-07-17 11:51:42 -07001038 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001039 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001040 uc_info = get_usecase_from_list(adev, in->usecase);
1041 if (uc_info == NULL) {
1042 ALOGE("%s: Could not find the usecase (%d) in the list",
1043 __func__, in->usecase);
1044 return -EINVAL;
1045 }
1046
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001047 /* Close in-call recording streams */
1048 voice_check_and_stop_incall_rec_usecase(adev, in);
1049
Eric Laurent150dbfe2013-02-27 14:31:02 -08001050 /* 1. Disable stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001051 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001052
1053 /* 2. Disable the tx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001054 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001055
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001056 list_remove(&uc_info->list);
1057 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001058
Eric Laurent994a6932013-07-17 11:51:42 -07001059 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060 return ret;
1061}
1062
1063int start_input_stream(struct stream_in *in)
1064{
1065 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001066 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001067 struct audio_usecase *uc_info;
1068 struct audio_device *adev = in->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301069 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001070
Ramjee Singh240ac652015-07-31 16:12:29 +05301071 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1072 if (get_usecase_from_list(adev, usecase) == NULL)
1073 in->usecase = usecase;
1074
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301075 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1076 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001077
Naresh Tannirucef332d2014-06-04 18:17:56 +05301078 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
1079 ALOGE("%s: sound card is not active/SSR returning error ", __func__);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301080 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301081 goto error_config;
1082 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301083
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001084 /* Check if source matches incall recording usecase criteria */
1085 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1086 if (ret)
1087 goto error_config;
1088 else
1089 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1090
Ramjee Singh240ac652015-07-31 16:12:29 +05301091 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1092 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1093 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1094 goto error_config;
1095 }
1096
Eric Laurentb23d5282013-05-14 15:27:20 -07001097 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001098 if (in->pcm_device_id < 0) {
1099 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1100 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001101 ret = -EINVAL;
1102 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001103 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001104
1105 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001106 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001107
1108 if (!uc_info) {
1109 ret = -ENOMEM;
1110 goto error_config;
1111 }
1112
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001113 uc_info->id = in->usecase;
1114 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001115 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001116 uc_info->devices = in->device;
1117 uc_info->in_snd_device = SND_DEVICE_NONE;
1118 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001119
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001120 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001121
1122 audio_extn_perf_lock_acquire();
1123
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125
Eric Laurentc8400632013-02-14 19:04:54 -08001126 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301127 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1128
1129 unsigned int flags = PCM_IN;
1130 unsigned int pcm_open_retry_entry_count = 0;
1131
1132 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1133 flags |= PCM_MMAP | PCM_NOIRQ;
1134 pcm_open_retry_entry_count = PROXY_OPEN_RETRY_COUNT;
1135 }
1136
1137 while(1) {
1138 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1139 flags, &in->config);
1140 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1141 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1142 if (in->pcm != NULL) {
1143 pcm_close(in->pcm);
1144 in->pcm = NULL;
1145 }
1146 if (pcm_open_retry_entry_count-- == 0) {
1147 ret = -EIO;
1148 goto error_open;
1149 }
1150 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1151 continue;
1152 }
1153 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001154 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301155
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001156 audio_extn_perf_lock_release();
1157
Eric Laurent994a6932013-07-17 11:51:42 -07001158 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001159 return ret;
1160
1161error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001162 stop_input_stream(in);
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001163 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001164
1165error_config:
1166 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001168
1169 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001170}
1171
Eric Laurent35455462015-06-19 16:30:44 -07001172void lock_input_stream(struct stream_in *in)
1173{
1174 pthread_mutex_lock(&in->pre_lock);
1175 pthread_mutex_lock(&in->lock);
1176 pthread_mutex_unlock(&in->pre_lock);
1177}
1178
1179void lock_output_stream(struct stream_out *out)
1180{
1181 pthread_mutex_lock(&out->pre_lock);
1182 pthread_mutex_lock(&out->lock);
1183 pthread_mutex_unlock(&out->pre_lock);
1184}
1185
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001186/* must be called with out->lock locked */
1187static int send_offload_cmd_l(struct stream_out* out, int command)
1188{
1189 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1190
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001191 if (!cmd) {
1192 ALOGE("failed to allocate mem for command 0x%x", command);
1193 return -ENOMEM;
1194 }
1195
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001196 ALOGVV("%s %d", __func__, command);
1197
1198 cmd->cmd = command;
1199 list_add_tail(&out->offload_cmd_list, &cmd->node);
1200 pthread_cond_signal(&out->offload_cond);
1201 return 0;
1202}
1203
1204/* must be called iwth out->lock locked */
1205static void stop_compressed_output_l(struct stream_out *out)
1206{
1207 out->offload_state = OFFLOAD_STATE_IDLE;
1208 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001209 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001210 if (out->compr != NULL) {
1211 compress_stop(out->compr);
1212 while (out->offload_thread_blocked) {
1213 pthread_cond_wait(&out->cond, &out->lock);
1214 }
1215 }
1216}
1217
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001218bool is_offload_usecase(audio_usecase_t uc_id)
1219{
1220 unsigned int i;
1221 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1222 if (uc_id == offload_usecases[i])
1223 return true;
1224 }
1225 return false;
1226}
1227
1228static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1229{
1230 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1231 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1232 char value[PROPERTY_VALUE_MAX] = {0};
1233
1234 property_get("audio.offload.multiple.enabled", value, NULL);
1235 if (!(atoi(value) || !strncmp("true", value, 4)))
1236 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1237
1238 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1239 for (i = 0; i < num_usecase; i++) {
1240 if (!(adev->offload_usecases_state & (0x1<<i))) {
1241 adev->offload_usecases_state |= 0x1 << i;
1242 ret = offload_usecases[i];
1243 break;
1244 }
1245 }
1246 ALOGV("%s: offload usecase is %d", __func__, ret);
1247 return ret;
1248}
1249
1250static void free_offload_usecase(struct audio_device *adev,
1251 audio_usecase_t uc_id)
1252{
1253 unsigned int i;
1254 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1255 if (offload_usecases[i] == uc_id) {
1256 adev->offload_usecases_state &= ~(0x1<<i);
1257 break;
1258 }
1259 }
1260 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1261}
1262
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001263static void *offload_thread_loop(void *context)
1264{
1265 struct stream_out *out = (struct stream_out *) context;
1266 struct listnode *item;
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001267 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001268
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001269 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1270 set_sched_policy(0, SP_FOREGROUND);
1271 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1272
1273 ALOGV("%s", __func__);
Eric Laurent35455462015-06-19 16:30:44 -07001274 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001275 for (;;) {
1276 struct offload_cmd *cmd = NULL;
1277 stream_callback_event_t event;
1278 bool send_callback = false;
1279
1280 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1281 __func__, list_empty(&out->offload_cmd_list),
1282 out->offload_state);
1283 if (list_empty(&out->offload_cmd_list)) {
1284 ALOGV("%s SLEEPING", __func__);
1285 pthread_cond_wait(&out->offload_cond, &out->lock);
1286 ALOGV("%s RUNNING", __func__);
1287 continue;
1288 }
1289
1290 item = list_head(&out->offload_cmd_list);
1291 cmd = node_to_item(item, struct offload_cmd, node);
1292 list_remove(item);
1293
1294 ALOGVV("%s STATE %d CMD %d out->compr %p",
1295 __func__, out->offload_state, cmd->cmd, out->compr);
1296
1297 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1298 free(cmd);
1299 break;
1300 }
1301
1302 if (out->compr == NULL) {
1303 ALOGE("%s: Compress handle is NULL", __func__);
1304 pthread_cond_signal(&out->cond);
1305 continue;
1306 }
1307 out->offload_thread_blocked = true;
1308 pthread_mutex_unlock(&out->lock);
1309 send_callback = false;
1310 switch(cmd->cmd) {
1311 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Steve Kondik05c17962015-02-25 00:55:50 -08001312 ALOGV("copl(%x):calling compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001313 compress_wait(out->compr, -1);
Steve Kondik05c17962015-02-25 00:55:50 -08001314 ALOGV("copl(%x):out of compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001315 send_callback = true;
1316 event = STREAM_CBK_EVENT_WRITE_READY;
1317 break;
1318 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001319 ret = compress_next_track(out->compr);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301320 if(ret == 0) {
Steve Kondik05c17962015-02-25 00:55:50 -08001321 ALOGV("copl(%p):calling compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301322 ret = compress_partial_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001323 ALOGV("copl(%p):out of compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301324 if (ret < 0)
1325 ret = -errno;
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301326 }
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301327 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001328 compress_drain(out->compr);
1329 else
1330 ALOGE("%s: Next track returned error %d",__func__, ret);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301331
1332 if (ret != -ENETRESET) {
1333 send_callback = true;
1334 event = STREAM_CBK_EVENT_DRAIN_READY;
1335
1336 /* Resend the metadata for next iteration */
1337 out->send_new_metadata = 1;
1338 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
1339 } else
1340 ALOGE("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001341 break;
1342 case OFFLOAD_CMD_DRAIN:
Steve Kondik05c17962015-02-25 00:55:50 -08001343 ALOGV("copl(%x):calling compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001344 compress_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001345 ALOGV("copl(%x):out of compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001346 send_callback = true;
1347 event = STREAM_CBK_EVENT_DRAIN_READY;
1348 break;
1349 default:
1350 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1351 break;
1352 }
Eric Laurent35455462015-06-19 16:30:44 -07001353 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001354 out->offload_thread_blocked = false;
1355 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001356 if (send_callback) {
Ravi Kumar Alamanda3d316172014-12-02 19:21:51 -08001357 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001358 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001359 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001360 free(cmd);
1361 }
1362
1363 pthread_cond_signal(&out->cond);
1364 while (!list_empty(&out->offload_cmd_list)) {
1365 item = list_head(&out->offload_cmd_list);
1366 list_remove(item);
1367 free(node_to_item(item, struct offload_cmd, node));
1368 }
1369 pthread_mutex_unlock(&out->lock);
1370
1371 return NULL;
1372}
1373
1374static int create_offload_callback_thread(struct stream_out *out)
1375{
1376 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1377 list_init(&out->offload_cmd_list);
1378 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1379 offload_thread_loop, out);
1380 return 0;
1381}
1382
1383static int destroy_offload_callback_thread(struct stream_out *out)
1384{
Eric Laurent35455462015-06-19 16:30:44 -07001385 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001386 stop_compressed_output_l(out);
1387 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1388
1389 pthread_mutex_unlock(&out->lock);
1390 pthread_join(out->offload_thread, (void **) NULL);
1391 pthread_cond_destroy(&out->offload_cond);
1392
1393 return 0;
1394}
1395
Eric Laurent07eeafd2013-10-06 12:52:49 -07001396static bool allow_hdmi_channel_config(struct audio_device *adev)
1397{
1398 struct listnode *node;
1399 struct audio_usecase *usecase;
1400 bool ret = true;
1401
1402 list_for_each(node, &adev->usecase_list) {
1403 usecase = node_to_item(node, struct audio_usecase, list);
1404 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1405 /*
1406 * If voice call is already existing, do not proceed further to avoid
1407 * disabling/enabling both RX and TX devices, CSD calls, etc.
1408 * Once the voice call done, the HDMI channels can be configured to
1409 * max channels of remaining use cases.
1410 */
1411 if (usecase->id == USECASE_VOICE_CALL) {
1412 ALOGD("%s: voice call is active, no change in HDMI channels",
1413 __func__);
1414 ret = false;
1415 break;
1416 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1417 ALOGD("%s: multi channel playback is active, "
1418 "no change in HDMI channels", __func__);
1419 ret = false;
1420 break;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001421 } else if (is_offload_usecase(usecase->id) &&
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301422 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin3ed162b2014-02-24 17:56:01 -08001423 ALOGD("%s: multi-channel(%x) compress offload playback is active, "
1424 "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
1425 ret = false;
1426 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001427 }
1428 }
1429 }
1430 return ret;
1431}
1432
1433static int check_and_set_hdmi_channels(struct audio_device *adev,
1434 unsigned int channels)
1435{
1436 struct listnode *node;
1437 struct audio_usecase *usecase;
1438
1439 /* Check if change in HDMI channel config is allowed */
1440 if (!allow_hdmi_channel_config(adev))
1441 return 0;
1442
1443 if (channels == adev->cur_hdmi_channels) {
Mingming Yin10fef6a2013-11-26 17:17:01 -08001444 ALOGD("%s: Requested channels are same as current channels(%d)", __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001445 return 0;
1446 }
1447
1448 platform_set_hdmi_channels(adev->platform, channels);
1449 adev->cur_hdmi_channels = channels;
1450
1451 /*
1452 * Deroute all the playback streams routed to HDMI so that
1453 * the back end is deactivated. Note that backend will not
1454 * be deactivated if any one stream is connected to it.
1455 */
1456 list_for_each(node, &adev->usecase_list) {
1457 usecase = node_to_item(node, struct audio_usecase, list);
1458 if (usecase->type == PCM_PLAYBACK &&
1459 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001460 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001461 }
1462 }
1463
1464 /*
1465 * Enable all the streams disabled above. Now the HDMI backend
1466 * will be activated with new channel configuration
1467 */
1468 list_for_each(node, &adev->usecase_list) {
1469 usecase = node_to_item(node, struct audio_usecase, list);
1470 if (usecase->type == PCM_PLAYBACK &&
1471 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001472 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001473 }
1474 }
1475
1476 return 0;
1477}
1478
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001479static int stop_output_stream(struct stream_out *out)
1480{
1481 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001482 struct audio_usecase *uc_info;
1483 struct audio_device *adev = out->dev;
1484
Eric Laurent994a6932013-07-17 11:51:42 -07001485 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001486 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001487 uc_info = get_usecase_from_list(adev, out->usecase);
1488 if (uc_info == NULL) {
1489 ALOGE("%s: Could not find the usecase (%d) in the list",
1490 __func__, out->usecase);
1491 return -EINVAL;
1492 }
1493
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001494 if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001495 if (adev->visualizer_stop_output != NULL)
1496 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1497 if (adev->offload_effects_stop_output != NULL)
1498 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1499 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001500
Eric Laurent150dbfe2013-02-27 14:31:02 -08001501 /* 1. Get and set stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001502 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001503
1504 /* 2. Disable the rx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001505 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001506
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001507 list_remove(&uc_info->list);
1508 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001509
Eric Laurentda46bfb2014-08-25 22:39:29 -05001510 audio_extn_extspk_update(adev->extspk);
1511
Eric Laurent07eeafd2013-10-06 12:52:49 -07001512 /* Must be called after removing the usecase from list */
1513 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1514 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1515
Eric Laurent994a6932013-07-17 11:51:42 -07001516 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001517 return ret;
1518}
1519
1520int start_output_stream(struct stream_out *out)
1521{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001522 int ret = 0;
Mingming Yin6c344432014-05-01 15:37:31 -07001523 int sink_channels = 0;
1524 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001525 struct audio_usecase *uc_info;
1526 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301527 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001528
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001529 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1530 ret = -EINVAL;
1531 goto error_config;
1532 }
1533
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301534 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1535 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1536 out->devices);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301537
Naresh Tannirucef332d2014-06-04 18:17:56 +05301538 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301539 ALOGE("%s: sound card is not active/SSR returning error", __func__);
1540 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301541 goto error_config;
1542 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301543
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301544 ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
1545 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001546 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001547 if (out->pcm_device_id < 0) {
1548 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1549 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001550 ret = -EINVAL;
1551 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001552 }
1553
1554 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001555
1556 if (!uc_info) {
1557 ret = -ENOMEM;
1558 goto error_config;
1559 }
1560
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001561 uc_info->id = out->usecase;
1562 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001563 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 uc_info->devices = out->devices;
1565 uc_info->in_snd_device = SND_DEVICE_NONE;
1566 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001567
Eric Laurent07eeafd2013-10-06 12:52:49 -07001568 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001569 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Mingming Yin6c344432014-05-01 15:37:31 -07001570 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1571 if (!strncmp("true", prop_value, 4)) {
1572 sink_channels = platform_edid_get_max_channels(out->dev->platform);
1573 ALOGD("%s: set HDMI channel count[%d] based on sink capability", __func__, sink_channels);
1574 check_and_set_hdmi_channels(adev, sink_channels);
1575 } else {
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001576 if (is_offload_usecase(out->usecase))
Mingming Yin6c344432014-05-01 15:37:31 -07001577 check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in);
1578 else
1579 check_and_set_hdmi_channels(adev, out->config.channels);
1580 }
Mingming Yin10fef6a2013-11-26 17:17:01 -08001581 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001582
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001583 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001584
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001585 audio_extn_perf_lock_acquire();
1586
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001587 select_devices(adev, out->usecase);
1588
Eric Laurentda46bfb2014-08-25 22:39:29 -05001589 audio_extn_extspk_update(adev->extspk);
1590
Steve Kondik3abbbc82014-11-29 14:14:43 -08001591 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1592 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
1593
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001594 if (!is_offload_usecase(out->usecase)) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301595 unsigned int flags = PCM_OUT;
1596 unsigned int pcm_open_retry_count = 0;
1597 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1598 flags |= PCM_MMAP | PCM_NOIRQ;
1599 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1600 } else
1601 flags |= PCM_MONOTONIC;
1602
1603 while (1) {
1604 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1605 flags, &out->config);
1606 if (out->pcm && !pcm_is_ready(out->pcm)) {
1607 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1608 if (out->pcm != NULL) {
1609 pcm_close(out->pcm);
1610 out->pcm = NULL;
1611 }
1612 if (pcm_open_retry_count-- == 0) {
1613 ret = -EIO;
1614 goto error_open;
1615 }
1616 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1617 continue;
1618 }
1619 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001620 }
1621 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001622 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001623 out->compr = compress_open(adev->snd_card,
1624 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001625 COMPRESS_IN, &out->compr_config);
1626 if (out->compr && !is_compress_ready(out->compr)) {
1627 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1628 compress_close(out->compr);
1629 out->compr = NULL;
1630 ret = -EIO;
1631 goto error_open;
1632 }
1633 if (out->offload_callback)
1634 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001635
Fred Oh1483d8a2015-03-04 18:42:34 -08001636 /* Since small bufs uses blocking writes, a write will be blocked
1637 for the default max poll time (20s) in the event of an SSR.
1638 Reduce the poll time to observe and deal with SSR faster.
1639 */
1640 if (out->use_small_bufs) {
1641 compress_set_max_poll_wait(out->compr, 1000);
1642 }
1643
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08001644#ifdef DS1_DOLBY_DDP_ENABLED
1645 if (audio_extn_is_dolby_format(out->format))
1646 audio_extn_dolby_send_ddp_endp_params(adev);
1647#endif
1648
Eric Laurentc4aef752013-09-12 17:45:53 -07001649 if (adev->visualizer_start_output != NULL)
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001650 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1651 if (adev->offload_effects_start_output != NULL)
1652 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001653 }
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001654 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001655 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001657error_open:
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001658 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001660error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001661 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662}
1663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001664static int check_input_parameters(uint32_t sample_rate,
1665 audio_format_t format,
1666 int channel_count)
1667{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001668 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001669
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001670 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001671 !voice_extn_compress_voip_is_format_supported(format) &&
1672 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001673
1674 switch (channel_count) {
1675 case 1:
1676 case 2:
1677 case 6:
1678 break;
1679 default:
1680 ret = -EINVAL;
1681 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001682
1683 switch (sample_rate) {
1684 case 8000:
1685 case 11025:
1686 case 12000:
1687 case 16000:
1688 case 22050:
1689 case 24000:
1690 case 32000:
1691 case 44100:
1692 case 48000:
1693 break;
1694 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001695 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001696 }
1697
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001698 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699}
1700
1701static size_t get_input_buffer_size(uint32_t sample_rate,
1702 audio_format_t format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001703 int channel_count,
1704 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001705{
1706 size_t size = 0;
1707
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001708 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1709 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001710
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001711 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001712 if (is_low_latency)
1713 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001714 /* ToDo: should use frame_size computed based on the format and
1715 channel_count here. */
1716 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001718 /* make sure the size is multiple of 32 bytes
1719 * At 48 kHz mono 16-bit PCM:
1720 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1721 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1722 */
1723 size += 0x1f;
1724 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001725
1726 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001727}
1728
1729static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1730{
1731 struct stream_out *out = (struct stream_out *)stream;
1732
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001733 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001734}
1735
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301736static int out_set_sample_rate(struct audio_stream *stream __unused,
1737 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001738{
1739 return -ENOSYS;
1740}
1741
1742static size_t out_get_buffer_size(const struct audio_stream *stream)
1743{
1744 struct stream_out *out = (struct stream_out *)stream;
1745
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001746 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001747 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001748 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1749 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001750
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301751 return out->config.period_size *
1752 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753}
1754
1755static uint32_t out_get_channels(const struct audio_stream *stream)
1756{
1757 struct stream_out *out = (struct stream_out *)stream;
1758
1759 return out->channel_mask;
1760}
1761
1762static audio_format_t out_get_format(const struct audio_stream *stream)
1763{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001764 struct stream_out *out = (struct stream_out *)stream;
1765
1766 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001767}
1768
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301769static int out_set_format(struct audio_stream *stream __unused,
1770 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001771{
1772 return -ENOSYS;
1773}
1774
1775static int out_standby(struct audio_stream *stream)
1776{
1777 struct stream_out *out = (struct stream_out *)stream;
1778 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001779
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301780 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1781 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001782 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1783 /* Ignore standby in case of voip call because the voip output
1784 * stream is closed in adev_close_output_stream()
1785 */
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301786 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001787 return 0;
1788 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789
Eric Laurent35455462015-06-19 16:30:44 -07001790 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001791 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001792 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07001793
1794 amplifier_output_stream_standby((struct audio_stream_out *) stream);
1795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001796 out->standby = true;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001797 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001798 if (out->pcm) {
1799 pcm_close(out->pcm);
1800 out->pcm = NULL;
1801 }
1802 } else {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301803 ALOGD("copl(%x):standby", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001804 stop_compressed_output_l(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001805 out->gapless_mdata.encoder_delay = 0;
1806 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 if (out->compr != NULL) {
1808 compress_close(out->compr);
1809 out->compr = NULL;
1810 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001811 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001812 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001813 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814 }
1815 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001816 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817 return 0;
1818}
1819
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301820static int out_dump(const struct audio_stream *stream __unused,
1821 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822{
1823 return 0;
1824}
1825
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001826static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1827{
1828 int ret = 0;
1829 char value[32];
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001830 bool is_meta_data_params = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001831 struct compr_gapless_mdata tmp_mdata;
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001832 tmp_mdata.encoder_delay = 0;
1833 tmp_mdata.encoder_padding = 0;
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001834
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001835 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001836 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001837 return -EINVAL;
1838 }
1839
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001840 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1841 if (ret >= 0) {
1842 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1843 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1844 ALOGV("ADTS format is set in offload mode");
1845 }
1846 out->send_new_metadata = 1;
1847 }
1848
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001849#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001850 if (out->format == AUDIO_FORMAT_FLAC) {
1851 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_BLK_SIZE, value, sizeof(value));
1852 if (ret >= 0) {
1853 out->compr_config.codec->options.flac_dec.min_blk_size = atoi(value);
1854 out->send_new_metadata = 1;
1855 }
1856 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_BLK_SIZE, value, sizeof(value));
1857 if (ret >= 0) {
1858 out->compr_config.codec->options.flac_dec.max_blk_size = atoi(value);
1859 out->send_new_metadata = 1;
1860 }
1861 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MIN_FRAME_SIZE, value, sizeof(value));
1862 if (ret >= 0) {
1863 out->compr_config.codec->options.flac_dec.min_frame_size = atoi(value);
1864 out->send_new_metadata = 1;
1865 }
1866 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FLAC_MAX_FRAME_SIZE, value, sizeof(value));
1867 if (ret >= 0) {
1868 out->compr_config.codec->options.flac_dec.max_frame_size = atoi(value);
1869 out->send_new_metadata = 1;
1870 }
1871 }
Steve Kondik6bedcdf2014-07-21 11:48:30 -07001872#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08001873
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001874 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_SAMPLE_RATE, value, sizeof(value));
1875 if(ret >= 0)
1876 is_meta_data_params = true;
1877 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_NUM_CHANNEL, value, sizeof(value));
1878 if(ret >= 0 )
1879 is_meta_data_params = true;
1880 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_AVG_BIT_RATE, value, sizeof(value));
1881 if(ret >= 0 )
1882 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001883 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1884 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001885 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001886 tmp_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001887 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001888 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1889 if (ret >= 0) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001890 is_meta_data_params = true;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001891 tmp_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001892 }
1893
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001894 if(!is_meta_data_params) {
1895 ALOGV("%s: Not gapless meta data params", __func__);
1896 return 0;
1897 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001898 out->gapless_mdata = tmp_mdata;
1899 out->send_new_metadata = 1;
1900 ALOGV("%s new encoder delay %u and padding %u", __func__,
1901 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1902
Steve Kondikba3b35d2014-07-18 01:49:48 -07001903 if(out->format == AUDIO_FORMAT_WMA || out->format == AUDIO_FORMAT_WMA_PRO) {
1904 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_FORMAT_TAG, value, sizeof(value));
1905 if (ret >= 0) {
1906 out->compr_config.codec->format = atoi(value);
1907 }
1908 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BLOCK_ALIGN, value, sizeof(value));
1909 if (ret >= 0) {
1910 out->compr_config.codec->options.wma.super_block_align = atoi(value);
1911 }
1912 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_BIT_PER_SAMPLE, value, sizeof(value));
1913 if (ret >= 0) {
1914 out->compr_config.codec->options.wma.bits_per_sample = atoi(value);
1915 }
1916 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_CHANNEL_MASK, value, sizeof(value));
1917 if (ret >= 0) {
1918 out->compr_config.codec->options.wma.channelmask = atoi(value);
1919 }
1920 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION, value, sizeof(value));
1921 if (ret >= 0) {
1922 out->compr_config.codec->options.wma.encodeopt = atoi(value);
1923 }
1924 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION1, value, sizeof(value));
1925 if (ret >= 0) {
1926 out->compr_config.codec->options.wma.encodeopt1 = atoi(value);
1927 }
1928 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_WMA_ENCODE_OPTION2, value, sizeof(value));
1929 if (ret >= 0) {
1930 out->compr_config.codec->options.wma.encodeopt2 = atoi(value);
1931 }
1932 ALOGV("WMA params: fmt %x, balgn %x, sr %d, chmsk %x, encop %x, op1 %x, op2 %x",
1933 out->compr_config.codec->format,
1934 out->compr_config.codec->options.wma.super_block_align,
1935 out->compr_config.codec->options.wma.bits_per_sample,
1936 out->compr_config.codec->options.wma.channelmask,
1937 out->compr_config.codec->options.wma.encodeopt,
1938 out->compr_config.codec->options.wma.encodeopt1,
1939 out->compr_config.codec->options.wma.encodeopt2);
1940 }
1941
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001942 return 0;
1943}
1944
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301945static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1946{
1947 return out == adev->primary_output || out == adev->voice_tx_output;
1948}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001949
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001950static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1951{
1952 struct stream_out *out = (struct stream_out *)stream;
1953 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001954 struct audio_usecase *usecase;
1955 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 struct str_parms *parms;
1957 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001958 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001959 bool select_new_device = false;
Steve Kondik3abbbc82014-11-29 14:14:43 -08001960 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961
sangwoobc677242013-08-08 16:53:43 +09001962 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001963 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001964 parms = str_parms_create_str(kvpairs);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001965 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1966 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 val = atoi(value);
Eric Laurent35455462015-06-19 16:30:44 -07001968 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001969 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001970
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001971 /*
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301972 * When HDMI cable is unplugged/usb hs is disconnected the
1973 * music playback is paused and the policy manager sends routing=0
1974 * But the audioflingercontinues to write data until standby time
1975 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001976 * Avoid this by routing audio to speaker until standby.
1977 */
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301978 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
Steve Kondikeadb6c82014-09-03 18:40:06 -07001979 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
1980 out->devices == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001981 val == AUDIO_DEVICE_NONE) {
1982 val = AUDIO_DEVICE_OUT_SPEAKER;
1983 }
1984
1985 /*
1986 * select_devices() call below switches all the usecases on the same
1987 * backend to the new device. Refer to check_usecases_codec_backend() in
1988 * the select_devices(). But how do we undo this?
1989 *
1990 * For example, music playback is active on headset (deep-buffer usecase)
1991 * and if we go to ringtones and select a ringtone, low-latency usecase
1992 * will be started on headset+speaker. As we can't enable headset+speaker
1993 * and headset devices at the same time, select_devices() switches the music
1994 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1995 * So when the ringtone playback is completed, how do we undo the same?
1996 *
1997 * We are relying on the out_set_parameters() call on deep-buffer output,
1998 * once the ringtone playback is ended.
1999 * NOTE: We should not check if the current devices are same as new devices.
2000 * Because select_devices() must be called to switch back the music
2001 * playback to headset.
2002 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002003 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002004 out->devices = val;
2005
2006 if (!out->standby)
2007 select_devices(adev, out->usecase);
2008
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002009 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302010 output_drives_call(adev, out)) {
2011 adev->current_call_output = out;
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07002012 if (!adev->voice.in_call)
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302013 ret = voice_start_call(adev);
2014 else
2015 voice_update_devices_for_all_voice_usecases(adev);
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07002016 }
2017 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002018
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07002019 if ((adev->mode == AUDIO_MODE_NORMAL) &&
2020 adev->voice.in_call &&
2021 output_drives_call(adev, out)) {
2022 ret = voice_stop_call(adev);
2023 adev->current_call_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002024 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002025
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002027 pthread_mutex_unlock(&out->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05002028
2029 /*handles device and call state changes*/
2030 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002032
2033 if (out == adev->primary_output) {
2034 pthread_mutex_lock(&adev->lock);
2035 audio_extn_set_parameters(adev, parms);
2036 pthread_mutex_unlock(&adev->lock);
2037 }
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002038 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002039 pthread_mutex_lock(&out->lock);
Steve Kondikba3b35d2014-07-18 01:49:48 -07002040 ret = parse_compress_metadata(out, parms);
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08002041 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002042 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07002043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002044 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002045 ALOGV("%s: exit: code(%d)", __func__, status);
2046 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002047}
2048
2049static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
2050{
2051 struct stream_out *out = (struct stream_out *)stream;
2052 struct str_parms *query = str_parms_create_str(keys);
2053 char *str;
2054 char value[256];
2055 struct str_parms *reply = str_parms_create();
2056 size_t i, j;
2057 int ret;
2058 bool first = true;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002059
2060 if (!query || !reply) {
2061 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
2062 return NULL;
2063 }
2064
Eric Laurent994a6932013-07-17 11:51:42 -07002065 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002066 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
2067 if (ret >= 0) {
2068 value[0] = '\0';
2069 i = 0;
2070 while (out->supported_channel_masks[i] != 0) {
2071 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2072 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2073 if (!first) {
2074 strcat(value, "|");
2075 }
2076 strcat(value, out_channels_name_to_enum_table[j].name);
2077 first = false;
2078 break;
2079 }
2080 }
2081 i++;
2082 }
2083 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2084 str = str_parms_to_str(reply);
2085 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002086 voice_extn_out_get_parameters(out, query, reply);
2087 str = str_parms_to_str(reply);
2088 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella2e032352014-01-29 12:52:19 -08002089 free(str);
2090 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002091 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002092 }
2093 str_parms_destroy(query);
2094 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002095 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002096 return str;
2097}
2098
2099static uint32_t out_get_latency(const struct audio_stream_out *stream)
2100{
2101 struct stream_out *out = (struct stream_out *)stream;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002102 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002103
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002104 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002105 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002106 } else {
2107 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002108 (out->config.rate);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002109 }
2110
Anish Kumar1a0594f2014-12-09 04:01:39 +05302111 ALOGV("%s: Latency %d", __func__, latency);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002112 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002113}
2114
2115static int out_set_volume(struct audio_stream_out *stream, float left,
2116 float right)
2117{
Eric Laurenta9024de2013-04-04 09:19:12 -07002118 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002119 int volume[2];
2120
Eric Laurenta9024de2013-04-04 09:19:12 -07002121 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2122 /* only take left channel into account: the API is for stereo anyway */
2123 out->muted = (left == 0.0f);
2124 return 0;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002125 } else if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002126 char mixer_ctl_name[128];
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002127 struct audio_device *adev = out->dev;
2128 struct mixer_ctl *ctl;
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002129 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2130 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002131
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002132 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2133 "Compress Playback %d Volume", pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002134 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2135 if (!ctl) {
2136 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2137 __func__, mixer_ctl_name);
2138 return -EINVAL;
2139 }
2140 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2141 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2142 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2143 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002144 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002145
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002146 return -ENOSYS;
2147}
2148
2149static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2150 size_t bytes)
2151{
2152 struct stream_out *out = (struct stream_out *)stream;
2153 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302154 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002155 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002156
Eric Laurent35455462015-06-19 16:30:44 -07002157 lock_output_stream(out);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302158
Naresh Tannirucef332d2014-06-04 18:17:56 +05302159 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
2160 if (out->pcm) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302161 ALOGD(" %s: sound card is not active/SSR state", __func__);
2162 ret= -ENETRESET;
2163 goto exit;
Alexy Joseph55204352014-10-06 12:15:01 -07002164 } else if (is_offload_usecase(out->usecase)) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302165 //during SSR for compress usecase we should return error to flinger
2166 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2167 pthread_mutex_unlock(&out->lock);
2168 return -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302169 }
2170 }
2171
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002172 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002173 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002174 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002175 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2176 ret = voice_extn_compress_voip_start_output_stream(out);
2177 else
2178 ret = start_output_stream(out);
Ethan Chen79c356c2015-06-07 12:26:14 -07002179
2180 if (ret == 0)
2181 amplifier_output_stream_start(stream,
2182 is_offload_usecase(out->usecase));
2183
Eric Laurent150dbfe2013-02-27 14:31:02 -08002184 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002185 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002186 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002187 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002188 goto exit;
2189 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002192 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002193 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002194 if (out->send_new_metadata) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302195 ALOGD("copl(%x):send new gapless metadata", (unsigned int)out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002196 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2197 out->send_new_metadata = 0;
2198 }
2199
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302201 if (ret < 0)
2202 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002203 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002204 if (ret >= 0 && ret < (ssize_t)bytes) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302205 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002206 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302207 } else if (-ENETRESET == ret) {
2208 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2209 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2210 pthread_mutex_unlock(&out->lock);
2211 out_standby(&out->stream.common);
2212 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002213 }
Naresh Tannirucef332d2014-06-04 18:17:56 +05302214 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002215 compress_start(out->compr);
2216 out->playback_started = 1;
2217 out->offload_state = OFFLOAD_STATE_PLAYING;
2218 }
2219 pthread_mutex_unlock(&out->lock);
2220 return ret;
2221 } else {
2222 if (out->pcm) {
2223 if (out->muted)
2224 memset((void *)buffer, 0, bytes);
2225 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302226 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2227 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2228 else
2229 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302230 if (ret < 0)
2231 ret = -errno;
2232 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002233 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002234 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002235 }
2236
2237exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302238 /* ToDo: There may be a corner case when SSR happens back to back during
2239 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302240 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302241 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302242 }
2243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244 pthread_mutex_unlock(&out->lock);
2245
2246 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002247 if (out->pcm)
2248 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302249 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302250 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302251 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302252 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302253 out->standby = true;
2254 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002255 out_standby(&out->stream.common);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002256 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
2257 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002258 }
2259 return bytes;
2260}
2261
2262static int out_get_render_position(const struct audio_stream_out *stream,
2263 uint32_t *dsp_frames)
2264{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002265 struct stream_out *out = (struct stream_out *)stream;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002266 if (is_offload_usecase(out->usecase) && (dsp_frames != NULL)) {
2267 ssize_t ret = 0;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002268 *dsp_frames = 0;
Eric Laurent35455462015-06-19 16:30:44 -07002269 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002270 if (out->compr != NULL) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302271 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002272 &out->sample_rate);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302273 if (ret < 0)
2274 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002275 ALOGVV("%s rendered frames %d sample_rate %d",
2276 __func__, *dsp_frames, out->sample_rate);
2277 }
2278 pthread_mutex_unlock(&out->lock);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302279 if (-ENETRESET == ret) {
2280 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2281 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2282 return -EINVAL;
2283 } else if(ret < 0) {
Steve Kondik81506242014-07-21 16:12:57 -07002284 if (out->compr == NULL) {
2285 return 0;
2286 }
2287 ALOGE(" ERROR: Unable to get time stamp from compress driver ret=%d", ret);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302288 return -EINVAL;
2289 } else {
2290 return 0;
2291 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002292 } else
2293 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002294}
2295
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302296static int out_add_audio_effect(const struct audio_stream *stream __unused,
2297 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002298{
2299 return 0;
2300}
2301
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302302static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2303 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002304{
2305 return 0;
2306}
2307
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302308static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2309 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002310{
2311 return -EINVAL;
2312}
2313
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002314static int out_get_presentation_position(const struct audio_stream_out *stream,
2315 uint64_t *frames, struct timespec *timestamp)
2316{
2317 struct stream_out *out = (struct stream_out *)stream;
2318 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002319 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002320
Eric Laurent35455462015-06-19 16:30:44 -07002321 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002322
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002323 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002324 if (out->compr != NULL) {
2325 compress_get_tstamp(out->compr, &dsp_frames,
2326 &out->sample_rate);
2327 ALOGVV("%s rendered frames %ld sample_rate %d",
2328 __func__, dsp_frames, out->sample_rate);
2329 *frames = dsp_frames;
2330 ret = 0;
2331 /* this is the best we can do */
2332 clock_gettime(CLOCK_MONOTONIC, timestamp);
2333 }
2334 } else {
2335 if (out->pcm) {
2336 size_t avail;
2337 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2338 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002339 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002340 // This adjustment accounts for buffering after app processor.
2341 // It is based on estimated DSP latency per use case, rather than exact.
2342 signed_frames -=
2343 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2344
Eric Laurent949a0892013-09-20 09:20:13 -07002345 // It would be unusual for this value to be negative, but check just in case ...
2346 if (signed_frames >= 0) {
2347 *frames = signed_frames;
2348 ret = 0;
2349 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002350 }
2351 }
2352 }
2353
2354 pthread_mutex_unlock(&out->lock);
2355
2356 return ret;
2357}
2358
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002359static int out_set_callback(struct audio_stream_out *stream,
2360 stream_callback_t callback, void *cookie)
2361{
2362 struct stream_out *out = (struct stream_out *)stream;
2363
2364 ALOGV("%s", __func__);
Eric Laurent35455462015-06-19 16:30:44 -07002365 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002366 out->offload_callback = callback;
2367 out->offload_cookie = cookie;
2368 pthread_mutex_unlock(&out->lock);
2369 return 0;
2370}
2371
2372static int out_pause(struct audio_stream_out* stream)
2373{
2374 struct stream_out *out = (struct stream_out *)stream;
2375 int status = -ENOSYS;
2376 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002377 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302378 ALOGD("copl(%x):pause compress driver", (unsigned int)out);
Eric Laurent35455462015-06-19 16:30:44 -07002379 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302381 struct audio_device *adev = out->dev;
2382 int snd_scard_state = get_snd_card_state(adev);
2383
2384 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2385 status = compress_pause(out->compr);
2386
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002387 out->offload_state = OFFLOAD_STATE_PAUSED;
2388 }
2389 pthread_mutex_unlock(&out->lock);
2390 }
2391 return status;
2392}
2393
2394static int out_resume(struct audio_stream_out* stream)
2395{
2396 struct stream_out *out = (struct stream_out *)stream;
2397 int status = -ENOSYS;
2398 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002399 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302400 ALOGD("copl(%x):resume compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002401 status = 0;
Eric Laurent35455462015-06-19 16:30:44 -07002402 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002403 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302404 struct audio_device *adev = out->dev;
2405 int snd_scard_state = get_snd_card_state(adev);
2406
2407 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2408 status = compress_resume(out->compr);
2409
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002410 out->offload_state = OFFLOAD_STATE_PLAYING;
2411 }
2412 pthread_mutex_unlock(&out->lock);
2413 }
2414 return status;
2415}
2416
2417static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2418{
2419 struct stream_out *out = (struct stream_out *)stream;
2420 int status = -ENOSYS;
2421 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002422 if (is_offload_usecase(out->usecase)) {
Eric Laurent35455462015-06-19 16:30:44 -07002423 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002424 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2425 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2426 else
2427 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2428 pthread_mutex_unlock(&out->lock);
2429 }
2430 return status;
2431}
2432
2433static int out_flush(struct audio_stream_out* stream)
2434{
2435 struct stream_out *out = (struct stream_out *)stream;
2436 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002437 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302438 ALOGD("copl(%x):calling compress flush", (unsigned int)out);
Eric Laurent35455462015-06-19 16:30:44 -07002439 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002440 stop_compressed_output_l(out);
2441 pthread_mutex_unlock(&out->lock);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302442 ALOGD("copl(%x):out of compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002443 return 0;
2444 }
2445 return -ENOSYS;
2446}
2447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002448/** audio_stream_in implementation **/
2449static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2450{
2451 struct stream_in *in = (struct stream_in *)stream;
2452
2453 return in->config.rate;
2454}
2455
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302456static int in_set_sample_rate(struct audio_stream *stream __unused,
2457 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002458{
2459 return -ENOSYS;
2460}
2461
2462static size_t in_get_buffer_size(const struct audio_stream *stream)
2463{
2464 struct stream_in *in = (struct stream_in *)stream;
2465
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002466 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2467 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002468 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2469 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002470
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302471 return in->config.period_size *
Steve Kondik3abbbc82014-11-29 14:14:43 -08002472 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473}
2474
2475static uint32_t in_get_channels(const struct audio_stream *stream)
2476{
2477 struct stream_in *in = (struct stream_in *)stream;
2478
2479 return in->channel_mask;
2480}
2481
2482static audio_format_t in_get_format(const struct audio_stream *stream)
2483{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002484 struct stream_in *in = (struct stream_in *)stream;
2485
2486 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487}
2488
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302489static int in_set_format(struct audio_stream *stream __unused,
2490 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002491{
2492 return -ENOSYS;
2493}
2494
2495static int in_standby(struct audio_stream *stream)
2496{
2497 struct stream_in *in = (struct stream_in *)stream;
2498 struct audio_device *adev = in->dev;
2499 int status = 0;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302500 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2501 stream, in->usecase, use_case_table[in->usecase]);
2502
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002503 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2504 /* Ignore standby in case of voip call because the voip input
2505 * stream is closed in adev_close_input_stream()
2506 */
2507 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2508 return status;
2509 }
2510
Eric Laurent35455462015-06-19 16:30:44 -07002511 lock_input_stream(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002512 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002513 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07002514
2515 amplifier_input_stream_standby((struct audio_stream_in *) stream);
2516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002517 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002518 if (in->pcm) {
2519 pcm_close(in->pcm);
2520 in->pcm = NULL;
2521 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002523 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002524 }
2525 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002526 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002527 return status;
2528}
2529
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302530static int in_dump(const struct audio_stream *stream __unused,
2531 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532{
2533 return 0;
2534}
2535
2536static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2537{
2538 struct stream_in *in = (struct stream_in *)stream;
2539 struct audio_device *adev = in->dev;
2540 struct str_parms *parms;
2541 char *str;
2542 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002543 int ret = 0, val = 0, err;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002544 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002545
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302546 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002547 parms = str_parms_create_str(kvpairs);
2548
Eric Laurent35455462015-06-19 16:30:44 -07002549 lock_input_stream(in);
2550
Eric Laurent150dbfe2013-02-27 14:31:02 -08002551 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002552
2553 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2554 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 val = atoi(value);
2556 /* no audio source uses val == 0 */
2557 if ((in->source != val) && (val != 0)) {
2558 in->source = val;
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002559 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2560 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2561 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2562 (in->config.rate == 8000 || in->config.rate == 16000) &&
Steve Kondikb6ab1fa2015-02-06 16:55:26 -08002563 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002564 err = voice_extn_compress_voip_open_input_stream(in);
2565 if (err != 0) {
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002566 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002567 __func__, err);
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002568 }
2569 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002570 }
2571 }
2572
Steve Kondik3abbbc82014-11-29 14:14:43 -08002573 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2574
2575 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002576 val = atoi(value);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302577 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002578 in->device = val;
2579 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002580 if (!in->standby)
Steve Kondik3abbbc82014-11-29 14:14:43 -08002581 status = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002582 }
2583 }
2584
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002585done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002586 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002587 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588
2589 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002590 ALOGV("%s: exit: status(%d)", __func__, status);
2591 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002592}
2593
2594static char* in_get_parameters(const struct audio_stream *stream,
2595 const char *keys)
2596{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002597 struct stream_in *in = (struct stream_in *)stream;
2598 struct str_parms *query = str_parms_create_str(keys);
2599 char *str;
2600 char value[256];
2601 struct str_parms *reply = str_parms_create();
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002602
2603 if (!query || !reply) {
2604 ALOGE("in_get_parameters: failed to create query or reply");
2605 return NULL;
2606 }
2607
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002608 ALOGV("%s: enter: keys - %s", __func__, keys);
2609
2610 voice_extn_in_get_parameters(in, query, reply);
2611
2612 str = str_parms_to_str(reply);
2613 str_parms_destroy(query);
2614 str_parms_destroy(reply);
2615
2616 ALOGV("%s: exit: returns - %s", __func__, str);
2617 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618}
2619
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302620static int in_set_gain(struct audio_stream_in *stream __unused,
2621 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002622{
2623 return 0;
2624}
2625
2626static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2627 size_t bytes)
2628{
2629 struct stream_in *in = (struct stream_in *)stream;
2630 struct audio_device *adev = in->dev;
2631 int i, ret = -1;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302632 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002633
Eric Laurent35455462015-06-19 16:30:44 -07002634 lock_input_stream(in);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302635
2636 if (in->pcm) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302637 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302638 ALOGD(" %s: sound card is not active/SSR state", __func__);
2639 ret= -ENETRESET;
2640 goto exit;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302641 }
2642 }
2643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002645 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002646 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2647 ret = voice_extn_compress_voip_start_input_stream(in);
2648 else
2649 ret = start_input_stream(in);
Ethan Chen79c356c2015-06-07 12:26:14 -07002650
2651 if (ret == 0)
2652 amplifier_input_stream_start(stream);
2653
Eric Laurent150dbfe2013-02-27 14:31:02 -08002654 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002656 goto exit;
2657 }
2658 in->standby = 0;
2659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660
2661 if (in->pcm) {
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302662 if (audio_extn_ssr_get_enabled() &&
2663 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002664 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002665 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2666 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302667 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2668 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002669 else
2670 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302671 if (ret < 0)
2672 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002673 }
2674
2675 /*
2676 * Instead of writing zeroes here, we could trust the hardware
2677 * to always provide zeroes when muted.
2678 */
Pavan Chikkala6c183fd2014-12-04 10:48:28 +05302679 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2680 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002681 memset(buffer, 0, bytes);
2682
2683exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302684 /* ToDo: There may be a corner case when SSR happens back to back during
2685 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302686 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302687 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302688 memset(buffer, 0, bytes);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302689 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 pthread_mutex_unlock(&in->lock);
2691
2692 if (ret != 0) {
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302693 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302694 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302695 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302696 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302697 in->standby = true;
2698 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 in_standby(&in->stream.common);
2700 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002701 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
2702 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002703 }
2704 return bytes;
2705}
2706
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302707static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002708{
2709 return 0;
2710}
2711
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002712static int add_remove_audio_effect(const struct audio_stream *stream,
2713 effect_handle_t effect,
2714 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002715{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002716 struct stream_in *in = (struct stream_in *)stream;
2717 int status = 0;
2718 effect_descriptor_t desc;
2719
2720 status = (*effect)->get_descriptor(effect, &desc);
2721 if (status != 0)
2722 return status;
2723
Eric Laurent35455462015-06-19 16:30:44 -07002724 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002725 pthread_mutex_lock(&in->dev->lock);
2726 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2727 in->enable_aec != enable &&
2728 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2729 in->enable_aec = enable;
2730 if (!in->standby)
2731 select_devices(in->dev, in->usecase);
2732 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002733 if (in->enable_ns != enable &&
2734 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2735 in->enable_ns = enable;
2736 if (!in->standby)
2737 select_devices(in->dev, in->usecase);
2738 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002739 pthread_mutex_unlock(&in->dev->lock);
2740 pthread_mutex_unlock(&in->lock);
2741
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742 return 0;
2743}
2744
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002745static int in_add_audio_effect(const struct audio_stream *stream,
2746 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747{
Eric Laurent994a6932013-07-17 11:51:42 -07002748 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002749 return add_remove_audio_effect(stream, effect, true);
2750}
2751
2752static int in_remove_audio_effect(const struct audio_stream *stream,
2753 effect_handle_t effect)
2754{
Eric Laurent994a6932013-07-17 11:51:42 -07002755 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002756 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757}
2758
2759static int adev_open_output_stream(struct audio_hw_device *dev,
2760 audio_io_handle_t handle,
2761 audio_devices_t devices,
2762 audio_output_flags_t flags,
2763 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302764 struct audio_stream_out **stream_out,
2765 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766{
2767 struct audio_device *adev = (struct audio_device *)dev;
2768 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002769 int i, ret = 0;
Steve Kondik5a447012014-12-02 16:04:20 -08002770 int32_t sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 *stream_out = NULL;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302773
2774 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2775 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehtac2711cd2015-08-26 14:01:20 -07002776 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tannirucef332d2014-06-04 18:17:56 +05302777 return -EINVAL;
2778 }
2779
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002780 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2781
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302782 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2783 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2784 devices, flags, &out->stream);
2785
2786
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002787 if (!out) {
2788 return -ENOMEM;
2789 }
2790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 if (devices == AUDIO_DEVICE_NONE)
2792 devices = AUDIO_DEVICE_OUT_SPEAKER;
2793
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002794 out->flags = flags;
2795 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002796 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002797 out->format = config->format;
2798 out->sample_rate = config->sample_rate;
2799 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2800 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002801 out->handle = handle;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002802 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002803 out->non_blocking = 0;
2804 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002805
2806 /* Init use case and pcm_config */
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002807 if ((out->flags == AUDIO_OUTPUT_FLAG_DIRECT) &&
Mingming Yinee733602014-04-03 17:47:22 -07002808 (
2809#ifdef AFE_PROXY_ENABLED
2810 out->devices & AUDIO_DEVICE_OUT_PROXY ||
2811#endif
2812 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002813
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002814 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002815 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2816 ret = read_hdmi_channel_masks(out);
2817
Mingming Yinee733602014-04-03 17:47:22 -07002818#ifdef AFE_PROXY_ENABLED
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002819 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2820 ret = audio_extn_read_afe_proxy_channel_masks(out);
Mingming Yinee733602014-04-03 17:47:22 -07002821#endif
2822
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002823 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002824 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002825 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002826
2827 if (config->sample_rate == 0)
2828 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2829 if (config->channel_mask == 0)
2830 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2831
2832 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002833 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2835 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002836 out->config.rate = config->sample_rate;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302837 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Mingming Yinee733602014-04-03 17:47:22 -07002839#ifdef COMPRESS_VOIP_ENABLED
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002840 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2841 (out->flags == (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002842 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002843 ret = voice_extn_compress_voip_open_output_stream(out);
2844 if (ret != 0) {
2845 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2846 __func__, ret);
2847 goto error_open;
2848 }
Mingming Yinee733602014-04-03 17:47:22 -07002849#endif
vivek mehtac2711cd2015-08-26 14:01:20 -07002850 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2851 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302852 ALOGD("%s: copl(%x): sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
2853 __func__, (unsigned int)out, config->sample_rate, config->channel_mask, devices, flags);
2854
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002855 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2856 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2857 ALOGE("%s: Unsupported Offload information", __func__);
2858 ret = -EINVAL;
2859 goto error_open;
2860 }
Mingming Yin90310102013-11-13 16:57:00 -08002861 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002862 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehtac2711cd2015-08-26 14:01:20 -07002863 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002864 ret = -EINVAL;
2865 goto error_open;
2866 }
2867
2868 out->compr_config.codec = (struct snd_codec *)
2869 calloc(1, sizeof(struct snd_codec));
2870
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002871 if (!out->compr_config.codec) {
2872 ret = -ENOMEM;
2873 goto error_open;
2874 }
2875
vivek mehtac2711cd2015-08-26 14:01:20 -07002876 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2877 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2878 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2879 } else {
2880 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2881 out->usecase = get_offload_usecase(adev);
2882 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002883 if (config->offload_info.channel_mask)
2884 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002885 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 out->channel_mask = config->channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002887 config->offload_info.channel_mask = config->channel_mask;
2888 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 out->format = config->offload_info.format;
2890 out->sample_rate = config->offload_info.sample_rate;
2891
2892 out->stream.set_callback = out_set_callback;
2893 out->stream.pause = out_pause;
2894 out->stream.resume = out_resume;
2895 out->stream.drain = out_drain;
2896 out->stream.flush = out_flush;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002897 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002899 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002900 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002901 audio_extn_dolby_get_snd_codec_id(adev, out,
2902 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002903 else
2904 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002905 get_snd_codec_id(config->offload_info.format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002906
vivek mehtac2711cd2015-08-26 14:01:20 -07002907 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2908 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002909 out->compr_config.fragment_size =
2910 platform_get_pcm_offload_buffer_size(&config->offload_info);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002911 } else {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002912 out->compr_config.fragment_size =
2913 platform_get_compress_offload_buffer_size(&config->offload_info);
2914 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0043e152014-10-23 14:42:59 -07002916#ifdef NEW_SAMPLE_RATE_ENABLED
2917 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
2918#else
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002919 out->compr_config.codec->sample_rate =
2920 compress_get_alsa_rate(config->offload_info.sample_rate);
Eric Laurent0043e152014-10-23 14:42:59 -07002921#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 out->compr_config.codec->bit_rate =
2923 config->offload_info.bit_rate;
2924 out->compr_config.codec->ch_in =
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302925 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002926 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002927 out->bit_width = config->offload_info.bit_width;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002928
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002929 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
Steve Kondik37454012014-11-23 19:54:21 -08002930 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002931 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2932 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002933 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002934 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehtac2711cd2015-08-26 14:01:20 -07002935 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
2936 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002937
Steve Kondik3abbbc82014-11-29 14:14:43 -08002938 if (out->bit_width == 24)
2939 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002940
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002941#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik37454012014-11-23 19:54:21 -08002942 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
2943 out->compr_config.codec->options.flac_dec.sample_size = config->offload_info.bit_width;
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002944#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002945
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002946 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2947 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002948
Mingming Yind48310a2015-06-10 16:28:10 -07002949 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002950 //this flag is set from framework only if its for PCM formats
2951 //no need to check for PCM format again
2952 out->non_blocking = 0;
2953 out->use_small_bufs = true;
2954 ALOGI("Keep write blocking for small buff: non_blockling %d",
2955 out->non_blocking);
2956 }
2957
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002958 out->send_new_metadata = 1;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002959 out->offload_state = OFFLOAD_STATE_IDLE;
2960 out->playback_started = 0;
2961
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002962 create_offload_callback_thread(out);
2963 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2964 __func__, config->offload_info.version,
2965 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002966 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -08002967 check_and_set_gapless_mode(adev);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002968
Mingming Yinee733602014-04-03 17:47:22 -07002969#ifdef INCALL_MUSIC_ENABLED
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002970 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2971 ret = voice_check_and_set_incall_music_usecase(adev, out);
2972 if (ret != 0) {
2973 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2974 __func__, ret);
2975 goto error_open;
2976 }
Mingming Yinee733602014-04-03 17:47:22 -07002977#endif
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302978 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2979 if (config->sample_rate == 0)
2980 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2981 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2982 config->sample_rate != 8000) {
2983 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2984 ret = -EINVAL;
2985 goto error_open;
2986 }
2987 out->sample_rate = config->sample_rate;
2988 out->config.rate = config->sample_rate;
2989 if (config->format == AUDIO_FORMAT_DEFAULT)
2990 config->format = AUDIO_FORMAT_PCM_16_BIT;
2991 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2992 config->format = AUDIO_FORMAT_PCM_16_BIT;
2993 ret = -EINVAL;
2994 goto error_open;
2995 }
2996 out->format = config->format;
2997 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2998 out->config = pcm_config_afe_proxy_playback;
2999 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003000 } else {
Steve Kondik3abbbc82014-11-29 14:14:43 -08003001#ifndef LOW_LATENCY_PRIMARY
3002 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
3003 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
3004 out->config = pcm_config_low_latency;
Steve Kondikb045f472014-11-12 23:24:07 -08003005#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -08003006#ifdef LOW_LATENCY_PRIMARY
3007 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
3008 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
3009 out->config = pcm_config_deep_buffer;
3010#endif
Ravi Kumar Alamanda8c884872015-06-25 20:08:01 -07003011 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
3012 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
3013 out->config = pcm_config_low_latency;
Steve Kondik3abbbc82014-11-29 14:14:43 -08003014 } else {
3015 /* primary path is the default path selected if no other outputs are available/suitable */
3016 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
3017#ifdef LOW_LATENCY_PRIMARY
3018 out->config = pcm_config_low_latency;
3019#else
3020 out->config = pcm_config_deep_buffer;
3021#endif
3022 }
3023 if (config->format != audio_format_from_pcm_format(out->config.format)) {
3024 if (k_enable_extended_precision
3025 && pcm_params_format_test(adev->use_case_table[out->usecase],
3026 pcm_format_from_audio_format(config->format))) {
3027 out->config.format = pcm_format_from_audio_format(config->format);
3028 /* out->format already set to config->format */
3029 } else {
3030 /* deny the externally proposed config format
3031 * and use the one specified in audio_hw layer configuration.
3032 * Note: out->format is returned by out->stream.common.get_format()
3033 * and is used to set config->format in the code several lines below.
3034 */
Steve Kondik5a447012014-12-02 16:04:20 -08003035 ALOGW("Audio format %x is not available on this output", out->format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08003036 out->format = audio_format_from_pcm_format(out->config.format);
3037 }
3038 }
3039
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003040 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003041 }
3042
Steve Kondik5a447012014-12-02 16:04:20 -08003043 ALOGV("%s flags %x, format %x, sample_rate %d, out->bit_width %d",
3044 __func__, flags, out->format, out->sample_rate, out->bit_width);
3045
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003046 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
Steve Kondik3abbbc82014-11-29 14:14:43 -08003047 flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003048 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003049 if(adev->primary_output == NULL)
3050 adev->primary_output = out;
3051 else {
3052 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003053 ret = -EEXIST;
3054 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003055 }
3056 }
3057
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003058 /* Check if this usecase is already existing */
3059 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella0d06c8e2014-04-17 20:00:41 -07003060 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3061 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003062 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003064 ret = -EEXIST;
3065 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 }
3067 pthread_mutex_unlock(&adev->lock);
3068
3069 out->stream.common.get_sample_rate = out_get_sample_rate;
3070 out->stream.common.set_sample_rate = out_set_sample_rate;
3071 out->stream.common.get_buffer_size = out_get_buffer_size;
3072 out->stream.common.get_channels = out_get_channels;
3073 out->stream.common.get_format = out_get_format;
3074 out->stream.common.set_format = out_set_format;
3075 out->stream.common.standby = out_standby;
3076 out->stream.common.dump = out_dump;
3077 out->stream.common.set_parameters = out_set_parameters;
3078 out->stream.common.get_parameters = out_get_parameters;
3079 out->stream.common.add_audio_effect = out_add_audio_effect;
3080 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3081 out->stream.get_latency = out_get_latency;
3082 out->stream.set_volume = out_set_volume;
3083 out->stream.write = out_write;
3084 out->stream.get_render_position = out_get_render_position;
3085 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003086 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003087
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003088 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003089 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003090 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003091
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303092 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurent35455462015-06-19 16:30:44 -07003093 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303094 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3095
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096 config->format = out->stream.common.get_format(&out->stream.common);
3097 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3098 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3099
3100 *stream_out = &out->stream;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303101 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehtac2711cd2015-08-26 14:01:20 -07003102 use_case_table[out->usecase]);
3103
Eric Laurent994a6932013-07-17 11:51:42 -07003104 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003106
3107error_open:
3108 free(out);
3109 *stream_out = NULL;
3110 ALOGD("%s: exit: ret %d", __func__, ret);
3111 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003112}
3113
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303114static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003115 struct audio_stream_out *stream)
3116{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003117 struct stream_out *out = (struct stream_out *)stream;
3118 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003119 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003120
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303121 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3122
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003123 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303124 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003125 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303126 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003127 if(ret != 0)
3128 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3129 __func__, ret);
3130 }
3131 else
3132 out_standby(&stream->common);
3133
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003134 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003135 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003136 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003137 if (out->compr_config.codec != NULL)
3138 free(out->compr_config.codec);
3139 }
3140 pthread_cond_destroy(&out->cond);
3141 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003142 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003143 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003144}
3145
Alexy Joseph55204352014-10-06 12:15:01 -07003146static void close_compress_sessions(struct audio_device *adev)
3147{
3148 struct stream_out *out = NULL;
3149 struct listnode *node = NULL;
3150 struct listnode *tmp = NULL;
3151 struct audio_usecase *usecase = NULL;
3152 pthread_mutex_lock(&adev->lock);
3153 list_for_each_safe(node, tmp, &adev->usecase_list) {
3154 usecase = node_to_item(node, struct audio_usecase, list);
3155 if (is_offload_usecase(usecase->id)) {
3156 if (usecase && usecase->stream.out) {
3157 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3158 out = usecase->stream.out;
3159 pthread_mutex_unlock(&adev->lock);
3160 out_standby(&out->stream.common);
3161 pthread_mutex_lock(&adev->lock);
3162 }
3163 }
3164 }
3165 pthread_mutex_unlock(&adev->lock);
3166}
3167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003168static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3169{
3170 struct audio_device *adev = (struct audio_device *)dev;
3171 struct str_parms *parms;
3172 char *str;
3173 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003174 int val;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303175 int ret;
3176 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003177
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003178 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003179 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003180
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303181 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3182 if (ret >= 0) {
3183 char *snd_card_status = value+2;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303184 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05303185 struct listnode *node;
3186 struct audio_usecase *usecase;
3187
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303188 ALOGD("Received sound card OFFLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303189 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3190
Alexy Joseph55204352014-10-06 12:15:01 -07003191 //close compress sessions on OFFLINE status
3192 close_compress_sessions(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303193 } else if (strstr(snd_card_status, "ONLINE")) {
3194 ALOGD("Received sound card ONLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303195 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303196 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303197 }
3198
3199 pthread_mutex_lock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303200 status = voice_set_parameters(adev, parms);
3201 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003202 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003203
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303204 status = platform_set_parameters(adev->platform, parms);
3205 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003206 goto done;
3207
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303208 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3209 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003210 /* When set to false, HAL should disable EC and NS
3211 * But it is currently not supported.
3212 */
3213 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3214 adev->bluetooth_nrec = true;
3215 else
3216 adev->bluetooth_nrec = false;
3217 }
3218
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303219 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3220 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003221 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3222 adev->screen_off = false;
3223 else
3224 adev->screen_off = true;
3225 }
3226
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303227 ret = str_parms_get_int(parms, "rotation", &val);
3228 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003229 bool reverse_speakers = false;
3230 switch(val) {
3231 // FIXME: note that the code below assumes that the speakers are in the correct placement
3232 // relative to the user when the device is rotated 90deg from its default rotation. This
3233 // assumption is device-specific, not platform-specific like this code.
3234 case 270:
3235 reverse_speakers = true;
3236 break;
3237 case 0:
3238 case 90:
3239 case 180:
3240 break;
3241 default:
3242 ALOGE("%s: unexpected rotation of %d", __func__, val);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303243 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003244 }
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303245 if (status == 0) {
3246 if (adev->speaker_lr_swap != reverse_speakers) {
3247 adev->speaker_lr_swap = reverse_speakers;
3248 // only update the selected device if there is active pcm playback
3249 struct audio_usecase *usecase;
3250 struct listnode *node;
3251 list_for_each(node, &adev->usecase_list) {
3252 usecase = node_to_item(node, struct audio_usecase, list);
3253 if (usecase->type == PCM_PLAYBACK) {
Steve Kondik3abbbc82014-11-29 14:14:43 -08003254 status = select_devices(adev, usecase->id);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303255 break;
3256 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003257 }
3258 }
3259 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003260 }
3261
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003262 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003263
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003264done:
3265 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003266 pthread_mutex_unlock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303267 ALOGV("%s: exit with code(%d)", __func__, status);
3268 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003269}
3270
3271static char* adev_get_parameters(const struct audio_hw_device *dev,
3272 const char *keys)
3273{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003274 struct audio_device *adev = (struct audio_device *)dev;
3275 struct str_parms *reply = str_parms_create();
3276 struct str_parms *query = str_parms_create_str(keys);
3277 char *str;
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303278 char value[256] = {0};
3279 int ret = 0;
3280
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003281 if (!query || !reply) {
3282 ALOGE("adev_get_parameters: failed to create query or reply");
3283 return NULL;
3284 }
3285
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303286 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
3287 sizeof(value));
3288 if (ret >=0) {
3289 int val = 1;
3290 pthread_mutex_lock(&adev->snd_card_status.lock);
3291 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3292 val = 0;
3293 pthread_mutex_unlock(&adev->snd_card_status.lock);
3294 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, val);
3295 goto exit;
3296 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003297
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003298 pthread_mutex_lock(&adev->lock);
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303299
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003300 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003301 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003302 platform_get_parameters(adev->platform, query, reply);
Naresh Tannirucef332d2014-06-04 18:17:56 +05303303 pthread_mutex_unlock(&adev->lock);
3304
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303305exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003306 str = str_parms_to_str(reply);
3307 str_parms_destroy(query);
3308 str_parms_destroy(reply);
3309
3310 ALOGV("%s: exit: returns - %s", __func__, str);
3311 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312}
3313
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303314static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003315{
3316 return 0;
3317}
3318
3319static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3320{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003321 int ret;
3322 struct audio_device *adev = (struct audio_device *)dev;
Eric Laurent321b96d2014-09-10 13:21:01 -05003323
3324 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3325
Haynes Mathew George5191a852013-09-11 14:19:36 -07003326 pthread_mutex_lock(&adev->lock);
3327 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003328 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003329 pthread_mutex_unlock(&adev->lock);
3330 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331}
3332
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303333static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3334 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003335{
3336 return -ENOSYS;
3337}
3338
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303339static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3340 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341{
3342 return -ENOSYS;
3343}
3344
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303345static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3346 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003347{
3348 return -ENOSYS;
3349}
3350
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303351static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3352 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003353{
3354 return -ENOSYS;
3355}
3356
3357static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3358{
3359 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003360 pthread_mutex_lock(&adev->lock);
3361 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003362 ALOGD("%s mode %d\n", __func__, mode);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303363 if (amplifier_set_mode(mode) != 0)
3364 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365 adev->mode = mode;
3366 }
3367 pthread_mutex_unlock(&adev->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003368
3369 audio_extn_extspk_set_mode(adev->extspk, mode);
3370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003371 return 0;
3372}
3373
3374static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3375{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003376 int ret;
3377
3378 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003379 ALOGD("%s state %d\n", __func__, state);
Shreyas Nagasandra Chandrasekhar9781c6c2014-12-01 05:49:35 -08003380 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003381 pthread_mutex_unlock(&adev->lock);
3382
3383 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384}
3385
3386static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3387{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003388 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 return 0;
3390}
3391
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303392static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 const struct audio_config *config)
3394{
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303395 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003396
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003397 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3398 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003399}
3400
3401static int adev_open_input_stream(struct audio_hw_device *dev,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303402 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003403 audio_devices_t devices,
3404 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303405 struct audio_stream_in **stream_in,
3406 audio_input_flags_t flags __unused,
3407 const char *address __unused,
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003408 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003409{
3410 struct audio_device *adev = (struct audio_device *)dev;
3411 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003412 int ret = 0, buffer_size, frame_size;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303413 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003414 bool is_low_latency = false;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303415
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003416 *stream_in = NULL;
3417 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3418 return -EINVAL;
3419
3420 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003421
3422 if (!in) {
3423 ALOGE("failed to allocate input stream");
3424 return -ENOMEM;
3425 }
3426
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303427 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003428 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3429 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003430
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003431 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurent35455462015-06-19 16:30:44 -07003432 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 in->stream.common.get_sample_rate = in_get_sample_rate;
3435 in->stream.common.set_sample_rate = in_set_sample_rate;
3436 in->stream.common.get_buffer_size = in_get_buffer_size;
3437 in->stream.common.get_channels = in_get_channels;
3438 in->stream.common.get_format = in_get_format;
3439 in->stream.common.set_format = in_set_format;
3440 in->stream.common.standby = in_standby;
3441 in->stream.common.dump = in_dump;
3442 in->stream.common.set_parameters = in_set_parameters;
3443 in->stream.common.get_parameters = in_get_parameters;
3444 in->stream.common.add_audio_effect = in_add_audio_effect;
3445 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3446 in->stream.set_gain = in_set_gain;
3447 in->stream.read = in_read;
3448 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3449
3450 in->device = devices;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003451 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 in->standby = 1;
3454 in->channel_mask = config->channel_mask;
3455
3456 /* Update config params with the requested sample rate and channels */
3457 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003458 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3459 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3460 is_low_latency = true;
3461#if LOW_LATENCY_CAPTURE_USE_CASE
3462 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3463#endif
3464 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003465 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003466 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003467 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003468
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303469 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkala3c0036d2014-12-17 16:45:10 +05303470 if (adev->mode != AUDIO_MODE_IN_CALL) {
3471 ret = -EINVAL;
3472 goto err_open;
Pavan Chikkala3ec42ef2014-11-21 20:57:48 +05303473 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303474 if (config->sample_rate == 0)
3475 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3476 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3477 config->sample_rate != 8000) {
3478 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3479 ret = -EINVAL;
3480 goto err_open;
3481 }
3482 if (config->format == AUDIO_FORMAT_DEFAULT)
3483 config->format = AUDIO_FORMAT_PCM_16_BIT;
3484 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3485 config->format = AUDIO_FORMAT_PCM_16_BIT;
3486 ret = -EINVAL;
3487 goto err_open;
3488 }
3489 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3490 in->config = pcm_config_afe_proxy_record;
3491 in->config.channels = channel_count;
3492 in->config.rate = config->sample_rate;
3493 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003494 if(audio_extn_ssr_get_enabled()) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303495 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003496 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3497 ret = -EINVAL;
3498 goto err_open;
3499 }
3500 } else {
Mingming Yindaf9c542014-09-16 17:41:33 -07003501 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003502 }
Mingming Yine62d7842013-10-25 16:26:03 -07003503 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08003504 audio_extn_compr_cap_format_supported(config->format) &&
3505 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303506 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003507 } else {
3508 in->config.channels = channel_count;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303509 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003510 buffer_size = get_input_buffer_size(config->sample_rate,
3511 config->format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003512 channel_count,
3513 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003514 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003515 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3516 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3517 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3518 (in->config.rate == 8000 || in->config.rate == 16000) &&
3519 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3520 voice_extn_compress_voip_open_input_stream(in);
3521 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003522 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003523
3524 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003525 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003526 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527
3528err_open:
3529 free(in);
3530 *stream_in = NULL;
3531 return ret;
3532}
3533
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303534static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535 struct audio_stream_in *stream)
3536{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003537 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003538 struct stream_in *in = (struct stream_in *)stream;
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303539 struct audio_device *adev = in->dev;
3540
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303541 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003542
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003543 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303544 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003545 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303546 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003547 if (ret != 0)
3548 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3549 __func__, ret);
3550 } else
3551 in_standby(&stream->common);
3552
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303553 if (audio_extn_ssr_get_enabled() &&
3554 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003555 audio_extn_ssr_deinit();
3556 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003557 free(stream);
3558
Mingming Yine62d7842013-10-25 16:26:03 -07003559 if(audio_extn_compr_cap_enabled() &&
3560 audio_extn_compr_cap_format_supported(in->config.format))
3561 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562 return;
3563}
3564
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303565static int adev_dump(const audio_hw_device_t *device __unused,
3566 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003567{
3568 return 0;
3569}
3570
Steve Kondik3abbbc82014-11-29 14:14:43 -08003571/* verifies input and output devices and their capabilities.
3572 *
3573 * This verification is required when enabling extended bit-depth or
3574 * sampling rates, as not all qcom products support it.
3575 *
3576 * Suitable for calling only on initialization such as adev_open().
3577 * It fills the audio_device use_case_table[] array.
3578 *
3579 * Has a side-effect that it needs to configure audio routing / devices
3580 * in order to power up the devices and read the device parameters.
3581 * It does not acquire any hw device lock. Should restore the devices
3582 * back to "normal state" upon completion.
3583 */
3584static int adev_verify_devices(struct audio_device *adev)
3585{
3586 /* enumeration is a bit difficult because one really wants to pull
3587 * the use_case, device id, etc from the hidden pcm_device_table[].
3588 * In this case there are the following use cases and device ids.
3589 *
3590 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3591 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3592 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3593 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3594 * [USECASE_AUDIO_RECORD] = {0, 0},
3595 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3596 * [USECASE_VOICE_CALL] = {2, 2},
3597 *
3598 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3599 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3600 */
3601
3602 /* should be the usecases enabled in adev_open_input_stream() */
3603 static const int test_in_usecases[] = {
3604 USECASE_AUDIO_RECORD,
3605 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3606 };
3607 /* should be the usecases enabled in adev_open_output_stream()*/
3608 static const int test_out_usecases[] = {
3609 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3610 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3611 };
3612 static const usecase_type_t usecase_type_by_dir[] = {
3613 PCM_PLAYBACK,
3614 PCM_CAPTURE,
3615 };
3616 static const unsigned flags_by_dir[] = {
3617 PCM_OUT,
3618 PCM_IN,
3619 };
3620
3621 size_t i;
3622 unsigned dir;
3623 const unsigned card_id = adev->snd_card;
3624 char info[512]; /* for possible debug info */
3625
3626 for (dir = 0; dir < 2; ++dir) {
3627 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3628 const unsigned flags_dir = flags_by_dir[dir];
3629 const size_t testsize =
3630 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3631 const int *testcases =
3632 dir ? test_in_usecases : test_out_usecases;
3633 const audio_devices_t audio_device =
3634 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3635
3636 for (i = 0; i < testsize; ++i) {
3637 const audio_usecase_t audio_usecase = testcases[i];
3638 int device_id;
3639 snd_device_t snd_device;
3640 struct pcm_params **pparams;
3641 struct stream_out out;
3642 struct stream_in in;
3643 struct audio_usecase uc_info;
3644 int retval;
3645
3646 pparams = &adev->use_case_table[audio_usecase];
3647 pcm_params_free(*pparams); /* can accept null input */
3648 *pparams = NULL;
3649
3650 /* find the device ID for the use case (signed, for error) */
3651 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3652 if (device_id < 0)
3653 continue;
3654
3655 /* prepare structures for device probing */
3656 memset(&uc_info, 0, sizeof(uc_info));
3657 uc_info.id = audio_usecase;
3658 uc_info.type = usecase_type;
3659 if (dir) {
3660 adev->active_input = &in;
3661 memset(&in, 0, sizeof(in));
3662 in.device = audio_device;
3663 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3664 uc_info.stream.in = &in;
3665 } else {
3666 adev->active_input = NULL;
3667 }
3668 memset(&out, 0, sizeof(out));
3669 out.devices = audio_device; /* only field needed in select_devices */
3670 uc_info.stream.out = &out;
3671 uc_info.devices = audio_device;
3672 uc_info.in_snd_device = SND_DEVICE_NONE;
3673 uc_info.out_snd_device = SND_DEVICE_NONE;
3674 list_add_tail(&adev->usecase_list, &uc_info.list);
3675
3676 /* select device - similar to start_(in/out)put_stream() */
3677 retval = select_devices(adev, audio_usecase);
3678 if (retval >= 0) {
3679 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3680#if LOG_NDEBUG == 0
3681 if (*pparams) {
3682 ALOGV("%s: (%s) card %d device %d", __func__,
3683 dir ? "input" : "output", card_id, device_id);
3684 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Steve Kondik13582572015-12-05 17:19:19 -08003685 ALOGV("parms: %s", info); /* print parameters */
Steve Kondik3abbbc82014-11-29 14:14:43 -08003686 } else {
3687 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3688 }
3689#endif
3690 }
3691
3692 /* deselect device - similar to stop_(in/out)put_stream() */
3693 /* 1. Get and set stream specific mixer controls */
3694 retval = disable_audio_route(adev, &uc_info);
3695 /* 2. Disable the rx device */
3696 retval = disable_snd_device(adev,
3697 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
3698 list_remove(&uc_info.list);
3699 }
3700 }
3701 adev->active_input = NULL; /* restore adev state */
3702 return 0;
3703}
3704
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003705static int adev_close(hw_device_t *device)
3706{
Steve Kondik3abbbc82014-11-29 14:14:43 -08003707 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003709
3710 if (!adev)
3711 return 0;
3712
3713 pthread_mutex_lock(&adev_init_lock);
3714
3715 if ((--audio_device_ref_count) == 0) {
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303716 if (amplifier_close() != 0)
3717 ALOGE("Amplifier close failed");
Kiran Kandide144c82013-11-20 15:58:32 -08003718 audio_extn_listen_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07003719 audio_route_free(adev->audio_route);
3720 free(adev->snd_dev_ref_cnt);
3721 platform_deinit(adev->platform);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003722 audio_extn_extspk_deinit(adev->extspk);
Steve Kondik3abbbc82014-11-29 14:14:43 -08003723 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3724 pcm_params_free(adev->use_case_table[i]);
3725 }
Kiran Kandi910e1862013-10-29 13:29:42 -07003726 free(device);
3727 adev = NULL;
3728 }
3729 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730 return 0;
3731}
3732
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003733/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3734 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3735 * just that it _might_ work.
3736 */
3737static int period_size_is_plausible_for_low_latency(int period_size)
3738{
3739 switch (period_size) {
3740 case 160:
3741 case 240:
3742 case 320:
3743 case 480:
3744 return 1;
3745 default:
3746 return 0;
3747 }
3748}
3749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750static int adev_open(const hw_module_t *module, const char *name,
3751 hw_device_t **device)
3752{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003753 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003754
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003755 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003756 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3757
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003758 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003759 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003760 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003761 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003762 ALOGD("%s: returning existing instance of adev", __func__);
3763 ALOGD("%s: exit", __func__);
3764 pthread_mutex_unlock(&adev_init_lock);
3765 return 0;
3766 }
3767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003768 adev = calloc(1, sizeof(struct audio_device));
3769
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003770 if (!adev) {
3771 pthread_mutex_unlock(&adev_init_lock);
3772 return -ENOMEM;
3773 }
3774
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003775 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003777 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3778 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3779 adev->device.common.module = (struct hw_module_t *)module;
3780 adev->device.common.close = adev_close;
3781
3782 adev->device.init_check = adev_init_check;
3783 adev->device.set_voice_volume = adev_set_voice_volume;
3784 adev->device.set_master_volume = adev_set_master_volume;
3785 adev->device.get_master_volume = adev_get_master_volume;
3786 adev->device.set_master_mute = adev_set_master_mute;
3787 adev->device.get_master_mute = adev_get_master_mute;
3788 adev->device.set_mode = adev_set_mode;
3789 adev->device.set_mic_mute = adev_set_mic_mute;
3790 adev->device.get_mic_mute = adev_get_mic_mute;
3791 adev->device.set_parameters = adev_set_parameters;
3792 adev->device.get_parameters = adev_get_parameters;
3793 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3794 adev->device.open_output_stream = adev_open_output_stream;
3795 adev->device.close_output_stream = adev_close_output_stream;
3796 adev->device.open_input_stream = adev_open_input_stream;
3797 adev->device.close_input_stream = adev_close_input_stream;
3798 adev->device.dump = adev_dump;
3799
3800 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003801 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003802 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003803 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003806 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003807 /* adev->cur_hdmi_channels = 0; by calloc() */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08003808 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3809 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003810 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003811 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003812 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly9b7e96b2014-02-14 14:45:49 -08003813 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003814 adev->offload_usecases_state = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003815
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303816 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3817 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
3818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003820 adev->platform = platform_init(adev);
3821 if (!adev->platform) {
3822 free(adev->snd_dev_ref_cnt);
3823 free(adev);
3824 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3825 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003826 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003827 return -EINVAL;
3828 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003829
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303830 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
Eric Laurentda46bfb2014-08-25 22:39:29 -05003831 adev->extspk = audio_extn_extspk_init(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303832
Eric Laurentc4aef752013-09-12 17:45:53 -07003833 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3834 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3835 if (adev->visualizer_lib == NULL) {
3836 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3837 } else {
3838 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3839 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003840 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003841 "visualizer_hal_start_output");
3842 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003843 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003844 "visualizer_hal_stop_output");
3845 }
3846 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003847 audio_extn_listen_init(adev, adev->snd_card);
Eric Laurentc4aef752013-09-12 17:45:53 -07003848
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003849 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3850 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3851 if (adev->offload_effects_lib == NULL) {
3852 ALOGE("%s: DLOPEN failed for %s", __func__,
3853 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3854 } else {
3855 ALOGV("%s: DLOPEN successful for %s", __func__,
3856 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3857 adev->offload_effects_start_output =
3858 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3859 "offload_effects_bundle_hal_start_output");
3860 adev->offload_effects_stop_output =
3861 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3862 "offload_effects_bundle_hal_stop_output");
3863 }
3864 }
3865
Dan Pasanend4c2ca92015-08-10 19:47:43 -05003866 if (amplifier_open() != 0)
3867 ALOGE("Amplifier initialization failed");
3868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869 *device = &adev->device.common;
Steve Kondik3abbbc82014-11-29 14:14:43 -08003870 if (k_enable_extended_precision)
3871 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003872
Kiran Kandi910e1862013-10-29 13:29:42 -07003873 audio_device_ref_count++;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003874
3875 char value[PROPERTY_VALUE_MAX];
3876 int trial;
3877 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3878 trial = atoi(value);
3879 if (period_size_is_plausible_for_low_latency(trial)) {
3880 pcm_config_low_latency.period_size = trial;
3881 pcm_config_low_latency.start_threshold = trial / 4;
3882 pcm_config_low_latency.avail_min = trial / 4;
3883 configured_low_latency_capture_period_size = trial;
3884 }
3885 }
3886 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3887 trial = atoi(value);
3888 if (period_size_is_plausible_for_low_latency(trial)) {
3889 configured_low_latency_capture_period_size = trial;
3890 }
3891 }
3892
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003893 pthread_mutex_unlock(&adev_init_lock);
3894
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07003895 audio_extn_perf_lock_init();
3896
Eric Laurent994a6932013-07-17 11:51:42 -07003897 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898 return 0;
3899}
3900
3901static struct hw_module_methods_t hal_module_methods = {
3902 .open = adev_open,
3903};
3904
3905struct audio_module HAL_MODULE_INFO_SYM = {
3906 .common = {
3907 .tag = HARDWARE_MODULE_TAG,
3908 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3909 .hal_api_version = HARDWARE_HAL_API_VERSION,
3910 .id = AUDIO_HARDWARE_MODULE_ID,
3911 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003912 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003913 .methods = &hal_module_methods,
3914 },
3915};