blob: 5dbb16eb70ee56242b06296614d0a0bf151ac05b [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
Amit Shekharfaefb322014-09-08 14:08:19 -070068#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_low_latency
Steve Kondikb045f472014-11-12 23:24:07 -080069#else
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080070#define USECASE_AUDIO_PLAYBACK_PRIMARY USECASE_AUDIO_PLAYBACK_DEEP_BUFFER
Amit Shekharfaefb322014-09-08 14:08:19 -070071#define PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY pcm_config_deep_buffer
Steve Kondikb045f472014-11-12 23:24:07 -080072#endif
Haynes Mathew Georgebf143712013-12-03 13:02:53 -080073
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -070074static unsigned int configured_low_latency_capture_period_size =
75 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
76
Steve Kondik3abbbc82014-11-29 14:14:43 -080077/* This constant enables extended precision handling.
Steve Kondik3abbbc82014-11-29 14:14:43 -080078 */
79static const bool k_enable_extended_precision = true;
80
Eric Laurentb23d5282013-05-14 15:27:20 -070081struct pcm_config pcm_config_deep_buffer = {
82 .channels = 2,
83 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
84 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
85 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
86 .format = PCM_FORMAT_S16_LE,
87 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
88 .stop_threshold = INT_MAX,
89 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
90};
91
92struct pcm_config pcm_config_low_latency = {
93 .channels = 2,
94 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
95 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
96 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
97 .format = PCM_FORMAT_S16_LE,
98 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
99 .stop_threshold = INT_MAX,
100 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
101};
102
103struct pcm_config pcm_config_hdmi_multi = {
104 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
105 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
106 .period_size = HDMI_MULTI_PERIOD_SIZE,
107 .period_count = HDMI_MULTI_PERIOD_COUNT,
108 .format = PCM_FORMAT_S16_LE,
109 .start_threshold = 0,
110 .stop_threshold = INT_MAX,
111 .avail_min = 0,
112};
113
114struct pcm_config pcm_config_audio_capture = {
115 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700116 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
117 .format = PCM_FORMAT_S16_LE,
Eric Laurent86659ab2015-07-06 17:54:15 -0700118 .stop_threshold = INT_MAX,
119 .avail_min = 0,
Eric Laurentb23d5282013-05-14 15:27:20 -0700120};
121
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530122#define AFE_PROXY_CHANNEL_COUNT 2
123#define AFE_PROXY_SAMPLING_RATE 48000
124
125#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
126#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
127
128struct pcm_config pcm_config_afe_proxy_playback = {
129 .channels = AFE_PROXY_CHANNEL_COUNT,
130 .rate = AFE_PROXY_SAMPLING_RATE,
131 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
132 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
133 .format = PCM_FORMAT_S16_LE,
134 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
135 .stop_threshold = INT_MAX,
136 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
137};
138
139#define AFE_PROXY_RECORD_PERIOD_SIZE 768
140#define AFE_PROXY_RECORD_PERIOD_COUNT 4
141
142struct pcm_config pcm_config_afe_proxy_record = {
143 .channels = AFE_PROXY_CHANNEL_COUNT,
144 .rate = AFE_PROXY_SAMPLING_RATE,
145 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
146 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
147 .format = PCM_FORMAT_S16_LE,
148 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
149 .stop_threshold = INT_MAX,
150 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
151};
152
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800153const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700154 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
155 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
156 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700157 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
Steve Kondik26d44522015-12-16 15:23:47 -0500158 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700159#ifdef MULTIPLE_OFFLOAD_ENABLED
160 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
161 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
162 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
163 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
164 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
165 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
166 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
167 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
168#endif
vivek mehtac2711cd2015-08-26 14:01:20 -0700169 [USECASE_AUDIO_DIRECT_PCM_OFFLOAD] = "compress-offload-playback2",
Eric Laurentb23d5282013-05-14 15:27:20 -0700170 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700171 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Eric Laurentb23d5282013-05-14 15:27:20 -0700172 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700173 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700174 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800175 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800176 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700177 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yinee733602014-04-03 17:47:22 -0700178
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700179 [USECASE_VOICE2_CALL] = "voice2-call",
180 [USECASE_VOLTE_CALL] = "volte-call",
181 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat111aeb32014-02-12 17:58:59 -0800182 [USECASE_VOWLAN_CALL] = "vowlan-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800183 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700184 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
185 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
186 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800187 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
188 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
189 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
190
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700191 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
192 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700193 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
194 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530195
196 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
197 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Eric Laurentb23d5282013-05-14 15:27:20 -0700198};
199
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700200static const audio_usecase_t offload_usecases[] = {
201 USECASE_AUDIO_PLAYBACK_OFFLOAD,
202#ifdef MULTIPLE_OFFLOAD_ENABLED
203 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
204 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
Steve Kondikac72feb2014-07-20 23:15:34 -0700205#ifndef PLATFORM_MSM8974
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700206 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
207 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
208 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
209 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
Steve Kondikac72feb2014-07-20 23:15:34 -0700210#endif
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700211 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
Steve Kondikac72feb2014-07-20 23:15:34 -0700212#ifndef PLATFORM_MSM8974
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700213 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
214#endif
Steve Kondikac72feb2014-07-20 23:15:34 -0700215#endif
vivek mehtac2711cd2015-08-26 14:01:20 -0700216 USECASE_AUDIO_DIRECT_PCM_OFFLOAD,
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -0700217};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800218
219#define STRING_TO_ENUM(string) { #string, string }
220
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800221struct string_to_enum {
222 const char *name;
223 uint32_t value;
224};
225
226static const struct string_to_enum out_channels_name_to_enum_table[] = {
227 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
228 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
229 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
230};
231
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700232static struct audio_device *adev = NULL;
233static pthread_mutex_t adev_init_lock;
Kiran Kandi910e1862013-10-29 13:29:42 -0700234static unsigned int audio_device_ref_count;
235
Haynes Mathew George5191a852013-09-11 14:19:36 -0700236static int set_voice_volume_l(struct audio_device *adev, float volume);
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800237
Ethan Chen79c356c2015-06-07 12:26:14 -0700238static amplifier_device_t * get_amplifier_device(void)
239{
Dan Pasanen46f76f52015-08-10 19:55:39 -0500240 if (adev)
241 return adev->amp;
242
243 return NULL;
244}
245
246static int amplifier_open(void)
247{
Ethan Chen79c356c2015-06-07 12:26:14 -0700248 int rc;
249 amplifier_module_t *module;
250
Ethan Chen79c356c2015-06-07 12:26:14 -0700251 rc = hw_get_module(AMPLIFIER_HARDWARE_MODULE_ID,
252 (const hw_module_t **) &module);
253 if (rc) {
254 ALOGV("%s: Failed to obtain reference to amplifier module: %s\n",
255 __func__, strerror(-rc));
Dan Pasanen46f76f52015-08-10 19:55:39 -0500256 return -ENODEV;
Ethan Chen79c356c2015-06-07 12:26:14 -0700257 }
258
259 rc = amplifier_device_open((const hw_module_t *) module, &adev->amp);
260 if (rc) {
261 ALOGV("%s: Failed to open amplifier hardware device: %s\n",
262 __func__, strerror(-rc));
Ethan Chen79c356c2015-06-07 12:26:14 -0700263 return -ENODEV;
264 }
265
266 return 0;
267}
268
269static int amplifier_set_input_devices(uint32_t devices)
270{
271 amplifier_device_t *amp = get_amplifier_device();
272 if (amp && amp->set_input_devices)
273 return amp->set_input_devices(amp, devices);
274
275 return 0;
276}
277
278static int amplifier_set_output_devices(uint32_t devices)
279{
280 amplifier_device_t *amp = get_amplifier_device();
281 if (amp && amp->set_output_devices)
282 return amp->set_output_devices(amp, devices);
283
284 return 0;
285}
286
Ethan Chen6720ae62015-07-03 21:35:30 -0700287static int amplifier_enable_devices(uint32_t devices, bool enable)
288{
289 amplifier_device_t *amp = get_amplifier_device();
290 bool is_output = devices > SND_DEVICE_OUT_BEGIN &&
291 devices < SND_DEVICE_OUT_END;
292
293 if (amp && amp->enable_output_devices && is_output)
294 return amp->enable_output_devices(amp, devices, enable);
295
296 if (amp && amp->enable_input_devices && !is_output)
297 return amp->enable_input_devices(amp, devices, enable);
298
299 return 0;
300}
301
Ethan Chen79c356c2015-06-07 12:26:14 -0700302static int amplifier_set_mode(audio_mode_t mode)
303{
304 amplifier_device_t *amp = get_amplifier_device();
305 if (amp && amp->set_mode)
306 return amp->set_mode(amp, mode);
307
308 return 0;
309}
310
311static int amplifier_output_stream_start(struct audio_stream_out *stream,
312 bool offload)
313{
314 amplifier_device_t *amp = get_amplifier_device();
315 if (amp && amp->output_stream_start)
316 return amp->output_stream_start(amp, stream, offload);
317
318 return 0;
319}
320
321static int amplifier_input_stream_start(struct audio_stream_in *stream)
322{
323 amplifier_device_t *amp = get_amplifier_device();
324 if (amp && amp->input_stream_start)
325 return amp->input_stream_start(amp, stream);
326
327 return 0;
328}
329
330static int amplifier_output_stream_standby(struct audio_stream_out *stream)
331{
332 amplifier_device_t *amp = get_amplifier_device();
333 if (amp && amp->output_stream_standby)
334 return amp->output_stream_standby(amp, stream);
335
336 return 0;
337}
338
339static int amplifier_input_stream_standby(struct audio_stream_in *stream)
340{
341 amplifier_device_t *amp = get_amplifier_device();
342 if (amp && amp->input_stream_standby)
343 return amp->input_stream_standby(amp, stream);
344
345 return 0;
346}
347
348static int amplifier_close(void)
349{
350 amplifier_device_t *amp = get_amplifier_device();
351 if (amp)
352 amplifier_device_close(amp);
353
354 return 0;
355}
356
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -0800357static int check_and_set_gapless_mode(struct audio_device *adev) {
358
359
360 char value[PROPERTY_VALUE_MAX] = {0};
361 bool gapless_enabled = false;
362 const char *mixer_ctl_name = "Compress Gapless Playback";
363 struct mixer_ctl *ctl;
364
365 ALOGV("%s:", __func__);
366 property_get("audio.offload.gapless.enabled", value, NULL);
367 gapless_enabled = atoi(value) || !strncmp("true", value, 4);
368
369 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
370 if (!ctl) {
371 ALOGE("%s: Could not get ctl for mixer cmd - %s",
372 __func__, mixer_ctl_name);
373 return -EINVAL;
374 }
375
376 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
377 ALOGE("%s: Could not set gapless mode %d",
378 __func__, gapless_enabled);
379 return -EINVAL;
380 }
381 return 0;
382}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700383
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700384static bool is_supported_format(audio_format_t format)
385{
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800386 switch (format) {
Steve Kondik3abbbc82014-11-29 14:14:43 -0800387 case AUDIO_FORMAT_MP3:
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800388 case AUDIO_FORMAT_PCM_16_BIT_OFFLOAD:
389 case AUDIO_FORMAT_PCM_24_BIT_OFFLOAD:
vivek mehtac2711cd2015-08-26 14:01:20 -0700390 case AUDIO_FORMAT_PCM_16_BIT:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700391#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik3abbbc82014-11-29 14:14:43 -0800392 case AUDIO_FORMAT_FLAC:
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700393#endif
Steve Kondik3abbbc82014-11-29 14:14:43 -0800394#ifdef WMA_OFFLOAD_ENABLED
395 case AUDIO_FORMAT_WMA:
396 case AUDIO_FORMAT_WMA_PRO:
397#endif
398#ifdef MP2_OFFLOAD_ENABLED
399 case AUDIO_FORMAT_MP2:
400#endif
401 case AUDIO_FORMAT_AAC_LC:
402 case AUDIO_FORMAT_AAC_HE_V1:
403 case AUDIO_FORMAT_AAC_HE_V2:
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530404 return true;
Steve Kondik3abbbc82014-11-29 14:14:43 -0800405
Steve Kondik3fdf4fc2014-12-10 21:15:43 -0800406 default:
407 return false;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530408 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700409 return false;
410}
411
412static int get_snd_codec_id(audio_format_t format)
413{
414 int id = 0;
415
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530416 switch (format & AUDIO_FORMAT_MAIN_MASK) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700417 case AUDIO_FORMAT_MP3:
418 id = SND_AUDIOCODEC_MP3;
419 break;
420 case AUDIO_FORMAT_AAC:
421 id = SND_AUDIOCODEC_AAC;
422 break;
Ashish Jaincff6e3e2014-08-25 20:36:25 +0530423 case AUDIO_FORMAT_PCM_OFFLOAD:
vivek mehtac2711cd2015-08-26 14:01:20 -0700424 case AUDIO_FORMAT_PCM:
ApurupaPattapu0c566872014-01-10 14:46:02 -0800425 id = SND_AUDIOCODEC_PCM;
426 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700427#ifdef FLAC_OFFLOAD_ENABLED
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800428 case AUDIO_FORMAT_FLAC:
429 id = SND_AUDIOCODEC_FLAC;
430 break;
Steve Kondik6bedcdf2014-07-21 11:48:30 -0700431#endif
Ethan Chenc856d972014-07-25 14:57:15 -0700432#ifdef WMA_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700433 case AUDIO_FORMAT_WMA:
434 id = SND_AUDIOCODEC_WMA;
435 break;
436 case AUDIO_FORMAT_WMA_PRO:
437 id = SND_AUDIOCODEC_WMA_PRO;
438 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700439#endif
440#ifdef MP2_OFFLOAD_ENABLED
Steve Kondikba3b35d2014-07-18 01:49:48 -0700441 case AUDIO_FORMAT_MP2:
442 id = SND_AUDIOCODEC_MP2;
443 break;
Ethan Chenc856d972014-07-25 14:57:15 -0700444#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700445 default:
Mingming Yin90310102013-11-13 16:57:00 -0800446 ALOGE("%s: Unsupported audio format :%x", __func__, format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700447 }
448
449 return id;
450}
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -0800451
Avinash Vaish8005dc82014-07-24 15:36:33 +0530452static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
453 struct audio_usecase *uc_info)
454{
455 struct listnode *node;
456 struct audio_usecase *usecase;
457
458 if (uc_info == NULL)
459 return -EINVAL;
460
461 /* Re-route all voice usecases on the shared backend other than the
462 specified usecase to new snd devices */
463 list_for_each(node, &adev->usecase_list) {
464 usecase = node_to_item(node, struct audio_usecase, list);
465 if ((usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) &&
466 (usecase != uc_info))
467 enable_audio_route(adev, usecase);
468 }
469 return 0;
470}
471
Venkata Narendra Kumar Guttac9e9e2c2014-07-09 16:29:28 +0530472int get_snd_card_state(struct audio_device *adev)
Naresh Tannirucef332d2014-06-04 18:17:56 +0530473{
474 int snd_scard_state;
475
476 if (!adev)
477 return SND_CARD_STATE_OFFLINE;
478
479 pthread_mutex_lock(&adev->snd_card_status.lock);
480 snd_scard_state = adev->snd_card_status.state;
481 pthread_mutex_unlock(&adev->snd_card_status.lock);
482
483 return snd_scard_state;
484}
485
486static int set_snd_card_state(struct audio_device *adev, int snd_scard_state)
487{
488 if (!adev)
489 return -ENOSYS;
490
491 pthread_mutex_lock(&adev->snd_card_status.lock);
492 adev->snd_card_status.state = snd_scard_state;
493 pthread_mutex_unlock(&adev->snd_card_status.lock);
494
495 return 0;
496}
497
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -0700498int pcm_ioctl(struct pcm *pcm, int request, ...)
499{
500 va_list ap;
501 void * arg;
502 int pcm_fd = *(int*)pcm;
503
504 va_start(ap, request);
505 arg = va_arg(ap, void *);
506 va_end(ap);
507
508 return ioctl(pcm_fd, request, arg);
509}
510
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700511int enable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700512 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800513{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700514 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700515 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800516
517 if (usecase == NULL)
518 return -EINVAL;
519
520 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
521
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800522 if (usecase->type == PCM_CAPTURE)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700523 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800524 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700525 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800526
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -0800527#ifdef DS1_DOLBY_DAP_ENABLED
528 audio_extn_dolby_set_dmid(adev);
529 audio_extn_dolby_set_endpoint(adev);
530#endif
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800531 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700532 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700533 ALOGV("%s: apply mixer and update path: %s", __func__, mixer_path);
534 audio_route_apply_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800535 ALOGV("%s: exit", __func__);
536 return 0;
537}
538
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700539int disable_audio_route(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700540 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800541{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700542 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700543 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800544
545 if (usecase == NULL)
546 return -EINVAL;
547
548 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700549 if (usecase->type == PCM_CAPTURE)
550 snd_device = usecase->in_snd_device;
551 else
552 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -0800553 strcpy(mixer_path, use_case_table[usecase->id]);
Eric Laurentb23d5282013-05-14 15:27:20 -0700554 platform_add_backend_name(mixer_path, snd_device);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700555 ALOGV("%s: reset and update mixer path: %s", __func__, mixer_path);
556 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800557 ALOGV("%s: exit", __func__);
558 return 0;
559}
560
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700561int enable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700562 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800563{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700564 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
565
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800566 if (snd_device < SND_DEVICE_MIN ||
567 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800568 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800569 return -EINVAL;
570 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700571
572 adev->snd_dev_ref_cnt[snd_device]++;
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700573
574 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0 ) {
575 ALOGE("%s: Invalid sound device returned", __func__);
576 return -EINVAL;
577 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700578 if (adev->snd_dev_ref_cnt[snd_device] > 1) {
Eric Laurent994a6932013-07-17 11:51:42 -0700579 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700580 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700581 return 0;
582 }
583
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700584 /* start usb playback thread */
585 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
586 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
587 audio_extn_usb_start_playback(adev);
588
589 /* start usb capture thread */
590 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
591 audio_extn_usb_start_capture(adev);
592
Tony Layher692f19a2015-01-03 13:16:45 -0500593 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
594 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700595 audio_extn_spkr_prot_is_enabled()) {
596 if (audio_extn_spkr_prot_start_processing(snd_device)) {
597 ALOGE("%s: spkr_start_processing failed", __func__);
598 return -EINVAL;
599 }
600 } else {
601 ALOGV("%s: snd_device(%d: %s)", __func__,
Steve Kondik0d268002015-10-16 01:57:18 -0700602 snd_device, device_name);
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700603 if (platform_send_audio_calibration(adev->platform, snd_device) < 0) {
604 adev->snd_dev_ref_cnt[snd_device]--;
605 return -EINVAL;
606 }
Steve Kondikad1a08a2015-11-11 16:26:25 +0100607 audio_extn_listen_update_status(snd_device,
608 LISTEN_EVENT_SND_DEVICE_BUSY);
Ethan Chen6720ae62015-07-03 21:35:30 -0700609 amplifier_enable_devices(snd_device, true);
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700610 audio_route_apply_and_update_path(adev->audio_route, device_name);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800611 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800612 return 0;
613}
614
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700615int disable_snd_device(struct audio_device *adev,
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700616 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800617{
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700618 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
619
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800620 if (snd_device < SND_DEVICE_MIN ||
621 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800622 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800623 return -EINVAL;
624 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700625 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
626 ALOGE("%s: device ref cnt is already 0", __func__);
627 return -EINVAL;
628 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700629
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700630 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -0700631
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700632 if(platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
633 ALOGE("%s: Invalid sound device returned", __func__);
634 return -EINVAL;
635 }
636
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700637 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Eric Laurent994a6932013-07-17 11:51:42 -0700638 ALOGV("%s: snd_device(%d: %s)", __func__,
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700639 snd_device, device_name);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -0800640 /* exit usb play back thread */
641 if(SND_DEVICE_OUT_USB_HEADSET == snd_device ||
642 SND_DEVICE_OUT_SPEAKER_AND_USB_HEADSET == snd_device)
643 audio_extn_usb_stop_playback();
644
645 /* exit usb capture thread */
646 if(SND_DEVICE_IN_USB_HEADSET_MIC == snd_device)
Rajshekar Eashwarappa4dfa0752014-10-02 20:18:20 +0530647 audio_extn_usb_stop_capture();
Tony Layher692f19a2015-01-03 13:16:45 -0500648
649 if ((snd_device == SND_DEVICE_OUT_SPEAKER ||
650 snd_device == SND_DEVICE_OUT_VOICE_SPEAKER) &&
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700651 audio_extn_spkr_prot_is_enabled()) {
652 audio_extn_spkr_prot_stop_processing();
Ethan Chen6720ae62015-07-03 21:35:30 -0700653 } else {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700654 audio_route_reset_and_update_path(adev->audio_route, device_name);
Ethan Chen6720ae62015-07-03 21:35:30 -0700655 amplifier_enable_devices(snd_device, false);
656 }
Kiran Kandide144c82013-11-20 15:58:32 -0800657
Steve Kondikad1a08a2015-11-11 16:26:25 +0100658 audio_extn_listen_update_status(snd_device,
Kiran Kandide144c82013-11-20 15:58:32 -0800659 LISTEN_EVENT_SND_DEVICE_FREE);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700660 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -0700661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800662 return 0;
663}
664
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700665static void check_usecases_codec_backend(struct audio_device *adev,
666 struct audio_usecase *uc_info,
667 snd_device_t snd_device)
668{
669 struct listnode *node;
670 struct audio_usecase *usecase;
671 bool switch_device[AUDIO_USECASE_MAX];
672 int i, num_uc_to_switch = 0;
673
674 /*
675 * This function is to make sure that all the usecases that are active on
676 * the hardware codec backend are always routed to any one device that is
677 * handled by the hardware codec.
678 * For example, if low-latency and deep-buffer usecases are currently active
679 * on speaker and out_set_parameters(headset) is received on low-latency
680 * output, then we have to make sure deep-buffer is also switched to headset,
681 * because of the limitation that both the devices cannot be enabled
682 * at the same time as they share the same backend.
683 */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800684 /*
685 * This call is to check if we need to force routing for a particular stream
686 * If there is a backend configuration change for the device when a
687 * new stream starts, then ADM needs to be closed and re-opened with the new
688 * configuraion. This call check if we need to re-route all the streams
689 * associated with the backend. Touch tone + 24 bit playback.
690 */
691 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info);
692
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700693 /* Disable all the usecases on the shared backend other than the
694 specified usecase */
695 for (i = 0; i < AUDIO_USECASE_MAX; i++)
696 switch_device[i] = false;
697
698 list_for_each(node, &adev->usecase_list) {
699 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800700 if (usecase->type != PCM_CAPTURE &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700701 usecase != uc_info &&
ApurupaPattapu9d6b4362014-02-27 10:24:11 -0800702 (usecase->out_snd_device != snd_device || force_routing) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700703 usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
704 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
705 __func__, use_case_table[usecase->id],
Eric Laurentb23d5282013-05-14 15:27:20 -0700706 platform_get_snd_device_name(usecase->out_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700707 disable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700708 switch_device[usecase->id] = true;
709 num_uc_to_switch++;
710 }
711 }
712
713 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700714 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700715
716 list_for_each(node, &adev->usecase_list) {
717 usecase = node_to_item(node, struct audio_usecase, list);
718 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700719 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700720 }
721 }
722
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700723 list_for_each(node, &adev->usecase_list) {
724 usecase = node_to_item(node, struct audio_usecase, list);
725 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700726 enable_snd_device(adev, snd_device);
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -0700727 }
728 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700729
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700730 /* Re-route all the usecases on the shared backend other than the
731 specified usecase to new snd devices */
732 list_for_each(node, &adev->usecase_list) {
733 usecase = node_to_item(node, struct audio_usecase, list);
734 /* Update the out_snd_device only before enabling the audio route */
735 if (switch_device[usecase->id] ) {
736 usecase->out_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530737 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
738 enable_audio_route(adev, usecase);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700739 }
740 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700741 }
742}
743
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700744static void check_and_route_capture_usecases(struct audio_device *adev,
745 struct audio_usecase *uc_info,
746 snd_device_t snd_device)
747{
748 struct listnode *node;
749 struct audio_usecase *usecase;
750 bool switch_device[AUDIO_USECASE_MAX];
751 int i, num_uc_to_switch = 0;
752
753 /*
754 * This function is to make sure that all the active capture usecases
755 * are always routed to the same input sound device.
756 * For example, if audio-record and voice-call usecases are currently
757 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
758 * is received for voice call then we have to make sure that audio-record
759 * usecase is also switched to earpiece i.e. voice-dmic-ef,
760 * because of the limitation that two devices cannot be enabled
761 * at the same time if they share the same backend.
762 */
763 for (i = 0; i < AUDIO_USECASE_MAX; i++)
764 switch_device[i] = false;
765
766 list_for_each(node, &adev->usecase_list) {
767 usecase = node_to_item(node, struct audio_usecase, list);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800768 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700769 usecase != uc_info &&
Avinash Vaish44014792015-03-27 14:46:04 +0530770 usecase->in_snd_device != snd_device &&
Narsinga Rao Chella2ae232a2015-07-08 19:38:38 -0700771 ((uc_info->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
772 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
773 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700774 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
775 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -0700776 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700777 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700778 switch_device[usecase->id] = true;
779 num_uc_to_switch++;
780 }
781 }
782
783 if (num_uc_to_switch) {
Haynes Mathew Georgef9306752014-04-24 11:53:44 -0700784 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700785
786 list_for_each(node, &adev->usecase_list) {
787 usecase = node_to_item(node, struct audio_usecase, list);
788 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700789 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -0800790 }
791 }
792
793 list_for_each(node, &adev->usecase_list) {
794 usecase = node_to_item(node, struct audio_usecase, list);
795 if (switch_device[usecase->id]) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700796 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700797 }
798 }
799
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700800 /* Re-route all the usecases on the shared backend other than the
801 specified usecase to new snd devices */
802 list_for_each(node, &adev->usecase_list) {
803 usecase = node_to_item(node, struct audio_usecase, list);
804 /* Update the in_snd_device only before enabling the audio route */
805 if (switch_device[usecase->id] ) {
806 usecase->in_snd_device = snd_device;
Avinash Vaish8005dc82014-07-24 15:36:33 +0530807 if (usecase->type != VOICE_CALL && usecase->type != VOIP_CALL)
808 enable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700809 }
810 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700811 }
812}
813
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800814/* must be called with hw device mutex locked */
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700815static int read_hdmi_channel_masks(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800816{
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700817 int ret = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -0700818 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800819
820 switch (channels) {
821 /*
822 * Do not handle stereo output in Multi-channel cases
823 * Stereo case is handled in normal playback path
824 */
825 case 6:
826 ALOGV("%s: HDMI supports 5.1", __func__);
827 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
828 break;
829 case 8:
830 ALOGV("%s: HDMI supports 5.1 and 7.1 channels", __func__);
831 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_5POINT1;
832 out->supported_channel_masks[1] = AUDIO_CHANNEL_OUT_7POINT1;
833 break;
834 default:
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700835 ALOGE("HDMI does not support multi channel playback");
836 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800837 break;
838 }
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -0700839 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800840}
841
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700842static audio_usecase_t get_voice_usecase_id_from_list(struct audio_device *adev)
843{
844 struct audio_usecase *usecase;
845 struct listnode *node;
846
847 list_for_each(node, &adev->usecase_list) {
848 usecase = node_to_item(node, struct audio_usecase, list);
849 if (usecase->type == VOICE_CALL) {
850 ALOGV("%s: usecase id %d", __func__, usecase->id);
851 return usecase->id;
852 }
853 }
854 return USECASE_INVALID;
855}
856
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700857struct audio_usecase *get_usecase_from_list(struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700858 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700859{
860 struct audio_usecase *usecase;
861 struct listnode *node;
862
863 list_for_each(node, &adev->usecase_list) {
864 usecase = node_to_item(node, struct audio_usecase, list);
865 if (usecase->id == uc_id)
866 return usecase;
867 }
868 return NULL;
869}
870
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700871int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800872{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800873 snd_device_t out_snd_device = SND_DEVICE_NONE;
874 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700875 struct audio_usecase *usecase = NULL;
876 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800877 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800878 struct audio_usecase *hfp_usecase = NULL;
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800879 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -0800880 struct listnode *node;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700881 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800882
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700883 usecase = get_usecase_from_list(adev, uc_id);
884 if (usecase == NULL) {
885 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
886 return -EINVAL;
887 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800888
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800889 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800890 (usecase->type == VOIP_CALL) ||
891 (usecase->type == PCM_HFP_CALL)) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700892 out_snd_device = platform_get_output_snd_device(adev->platform,
893 usecase->stream.out->devices);
894 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700895 usecase->devices = usecase->stream.out->devices;
896 } else {
897 /*
898 * If the voice call is active, use the sound devices of voice call usecase
899 * so that it would not result any device switch. All the usecases will
900 * be switched to new device when select_devices() is called for voice call
901 * usecase. This is to avoid switching devices for voice call when
902 * check_usecases_codec_backend() is called below.
903 */
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -0700904 if (adev->voice.in_call && adev->mode == AUDIO_MODE_IN_CALL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700905 vc_usecase = get_usecase_from_list(adev,
906 get_voice_usecase_id_from_list(adev));
Mingming Yin6c23f382014-08-14 00:00:51 -0700907 if ((vc_usecase) && ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
908 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700909 in_snd_device = vc_usecase->in_snd_device;
910 out_snd_device = vc_usecase->out_snd_device;
911 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800912 } else if (voice_extn_compress_voip_is_active(adev)) {
913 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
Mingming Yin6c23f382014-08-14 00:00:51 -0700914 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Avinash Vaish6a4c3372014-06-25 12:20:37 +0530915 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Mingming Yin6c23f382014-08-14 00:00:51 -0700916 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800917 in_snd_device = voip_usecase->in_snd_device;
918 out_snd_device = voip_usecase->out_snd_device;
919 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800920 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed739e7152014-01-23 15:56:53 -0800921 hfp_ucid = audio_extn_hfp_get_usecase();
922 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin6c23f382014-08-14 00:00:51 -0700923 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -0800924 in_snd_device = hfp_usecase->in_snd_device;
925 out_snd_device = hfp_usecase->out_snd_device;
926 }
Vimal Puthanveed8fa9eab2014-01-07 16:47:47 -0800927 } else if (audio_extn_hfp_is_active(adev)) {
928 hfp_usecase = get_usecase_from_list(adev, USECASE_AUDIO_HFP_SCO);
929 if (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) {
930 in_snd_device = hfp_usecase->in_snd_device;
931 out_snd_device = hfp_usecase->out_snd_device;
932 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 }
934 if (usecase->type == PCM_PLAYBACK) {
935 usecase->devices = usecase->stream.out->devices;
936 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700937 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700938 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700939 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700940 if (usecase->stream.out == adev->primary_output &&
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530941 adev->active_input ) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700942 select_devices(adev, adev->active_input->usecase);
943 }
944 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700945 } else if (usecase->type == PCM_CAPTURE) {
946 usecase->devices = usecase->stream.in->device;
947 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700948 if (in_snd_device == SND_DEVICE_NONE) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530949 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530950 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 -0700951 adev->primary_output && !adev->primary_output->standby) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530952 out_device = adev->primary_output->devices;
953 } else if(usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
954 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700955 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530956 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700957 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700958 }
959 }
960
961 if (out_snd_device == usecase->out_snd_device &&
962 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800963 return 0;
964 }
965
sangwoobc677242013-08-08 16:53:43 +0900966 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700967 out_snd_device, platform_get_snd_device_name(out_snd_device),
968 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800970 /*
971 * Limitation: While in call, to do a device switch we need to disable
972 * and enable both RX and TX devices though one of them is same as current
973 * device.
974 */
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800975 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700976 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800977 }
978
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700979 /* Disable current sound devices */
980 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700981 disable_audio_route(adev, usecase);
982 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800983 }
984
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700985 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700986 disable_audio_route(adev, usecase);
987 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800988 }
989
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700990 /* Enable new sound devices */
991 if (out_snd_device != SND_DEVICE_NONE) {
992 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
993 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700994 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995 }
996
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -0700997 if (in_snd_device != SND_DEVICE_NONE) {
998 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700999 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001000 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001001
Avinash Vaish8005dc82014-07-24 15:36:33 +05301002 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001003 status = platform_switch_voice_call_device_post(adev->platform,
1004 out_snd_device,
1005 in_snd_device);
Avinash Vaish8005dc82014-07-24 15:36:33 +05301006 enable_audio_route_for_voice_usecases(adev, usecase);
1007 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001008
sangwoo170731f2013-06-08 15:36:36 +09001009 usecase->in_snd_device = in_snd_device;
1010 usecase->out_snd_device = out_snd_device;
1011
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001012 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001013
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301014 /* Rely on amplifier_set_devices to distinguish between in/out devices */
Ethan Chen79c356c2015-06-07 12:26:14 -07001015 amplifier_set_input_devices(in_snd_device);
1016 amplifier_set_output_devices(out_snd_device);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301017
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001018 /* Applicable only on the targets that has external modem.
1019 * Enable device command should be sent to modem only after
1020 * enabling voice call mixer controls
1021 */
1022 if (usecase->type == VOICE_CALL)
1023 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1024 out_snd_device,
1025 in_snd_device);
1026
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301027 ALOGD("%s: done",__func__);
1028
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001029 return status;
1030}
1031
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001032static int stop_input_stream(struct stream_in *in)
1033{
1034 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001035 struct audio_usecase *uc_info;
1036 struct audio_device *adev = in->dev;
1037
Eric Laurentc8400632013-02-14 19:04:54 -08001038 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001039
Eric Laurent994a6932013-07-17 11:51:42 -07001040 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001041 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001042 uc_info = get_usecase_from_list(adev, in->usecase);
1043 if (uc_info == NULL) {
1044 ALOGE("%s: Could not find the usecase (%d) in the list",
1045 __func__, in->usecase);
1046 return -EINVAL;
1047 }
1048
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001049 /* Close in-call recording streams */
1050 voice_check_and_stop_incall_rec_usecase(adev, in);
1051
Eric Laurent150dbfe2013-02-27 14:31:02 -08001052 /* 1. Disable stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001053 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001054
1055 /* 2. Disable the tx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001056 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001058 list_remove(&uc_info->list);
1059 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001060
Eric Laurent994a6932013-07-17 11:51:42 -07001061 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001062 return ret;
1063}
1064
1065int start_input_stream(struct stream_in *in)
1066{
1067 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001068 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001069 struct audio_usecase *uc_info;
1070 struct audio_device *adev = in->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301071 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072
Ramjee Singh240ac652015-07-31 16:12:29 +05301073 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1074 if (get_usecase_from_list(adev, usecase) == NULL)
1075 in->usecase = usecase;
1076
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301077 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1078 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001079
Naresh Tannirucef332d2014-06-04 18:17:56 +05301080 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
1081 ALOGE("%s: sound card is not active/SSR returning error ", __func__);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301082 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301083 goto error_config;
1084 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301085
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001086 /* Check if source matches incall recording usecase criteria */
1087 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1088 if (ret)
1089 goto error_config;
1090 else
1091 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1092
Ramjee Singh240ac652015-07-31 16:12:29 +05301093 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1094 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1095 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1096 goto error_config;
1097 }
1098
Eric Laurentb23d5282013-05-14 15:27:20 -07001099 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001100 if (in->pcm_device_id < 0) {
1101 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1102 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001103 ret = -EINVAL;
1104 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001106
1107 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001108 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001109
1110 if (!uc_info) {
1111 ret = -ENOMEM;
1112 goto error_config;
1113 }
1114
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001115 uc_info->id = in->usecase;
1116 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001117 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118 uc_info->devices = in->device;
1119 uc_info->in_snd_device = SND_DEVICE_NONE;
1120 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001121
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001122 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001123
1124 audio_extn_perf_lock_acquire();
1125
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001126 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127
Eric Laurentc8400632013-02-14 19:04:54 -08001128 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301129 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1130
1131 unsigned int flags = PCM_IN;
1132 unsigned int pcm_open_retry_entry_count = 0;
1133
1134 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1135 flags |= PCM_MMAP | PCM_NOIRQ;
1136 pcm_open_retry_entry_count = PROXY_OPEN_RETRY_COUNT;
1137 }
1138
1139 while(1) {
1140 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1141 flags, &in->config);
1142 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1143 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1144 if (in->pcm != NULL) {
1145 pcm_close(in->pcm);
1146 in->pcm = NULL;
1147 }
1148 if (pcm_open_retry_entry_count-- == 0) {
1149 ret = -EIO;
1150 goto error_open;
1151 }
1152 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1153 continue;
1154 }
1155 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301157
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001158 audio_extn_perf_lock_release();
1159
Eric Laurent994a6932013-07-17 11:51:42 -07001160 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001161 return ret;
1162
1163error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164 stop_input_stream(in);
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001165 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001166
1167error_config:
1168 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001169 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001170
1171 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001172}
1173
Eric Laurent35455462015-06-19 16:30:44 -07001174void lock_input_stream(struct stream_in *in)
1175{
1176 pthread_mutex_lock(&in->pre_lock);
1177 pthread_mutex_lock(&in->lock);
1178 pthread_mutex_unlock(&in->pre_lock);
1179}
1180
1181void lock_output_stream(struct stream_out *out)
1182{
1183 pthread_mutex_lock(&out->pre_lock);
1184 pthread_mutex_lock(&out->lock);
1185 pthread_mutex_unlock(&out->pre_lock);
1186}
1187
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001188/* must be called with out->lock locked */
1189static int send_offload_cmd_l(struct stream_out* out, int command)
1190{
1191 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1192
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001193 if (!cmd) {
1194 ALOGE("failed to allocate mem for command 0x%x", command);
1195 return -ENOMEM;
1196 }
1197
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001198 ALOGVV("%s %d", __func__, command);
1199
1200 cmd->cmd = command;
1201 list_add_tail(&out->offload_cmd_list, &cmd->node);
1202 pthread_cond_signal(&out->offload_cond);
1203 return 0;
1204}
1205
1206/* must be called iwth out->lock locked */
1207static void stop_compressed_output_l(struct stream_out *out)
1208{
1209 out->offload_state = OFFLOAD_STATE_IDLE;
1210 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001211 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001212 if (out->compr != NULL) {
1213 compress_stop(out->compr);
1214 while (out->offload_thread_blocked) {
1215 pthread_cond_wait(&out->cond, &out->lock);
1216 }
1217 }
1218}
1219
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001220bool is_offload_usecase(audio_usecase_t uc_id)
1221{
1222 unsigned int i;
1223 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1224 if (uc_id == offload_usecases[i])
1225 return true;
1226 }
1227 return false;
1228}
1229
1230static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1231{
1232 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1233 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1234 char value[PROPERTY_VALUE_MAX] = {0};
1235
1236 property_get("audio.offload.multiple.enabled", value, NULL);
1237 if (!(atoi(value) || !strncmp("true", value, 4)))
1238 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1239
1240 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1241 for (i = 0; i < num_usecase; i++) {
1242 if (!(adev->offload_usecases_state & (0x1<<i))) {
1243 adev->offload_usecases_state |= 0x1 << i;
1244 ret = offload_usecases[i];
1245 break;
1246 }
1247 }
1248 ALOGV("%s: offload usecase is %d", __func__, ret);
1249 return ret;
1250}
1251
1252static void free_offload_usecase(struct audio_device *adev,
1253 audio_usecase_t uc_id)
1254{
1255 unsigned int i;
1256 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1257 if (offload_usecases[i] == uc_id) {
1258 adev->offload_usecases_state &= ~(0x1<<i);
1259 break;
1260 }
1261 }
1262 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1263}
1264
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001265static void *offload_thread_loop(void *context)
1266{
1267 struct stream_out *out = (struct stream_out *) context;
1268 struct listnode *item;
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001269 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001270
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001271 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1272 set_sched_policy(0, SP_FOREGROUND);
1273 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1274
1275 ALOGV("%s", __func__);
Eric Laurent35455462015-06-19 16:30:44 -07001276 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001277 for (;;) {
1278 struct offload_cmd *cmd = NULL;
1279 stream_callback_event_t event;
1280 bool send_callback = false;
1281
1282 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1283 __func__, list_empty(&out->offload_cmd_list),
1284 out->offload_state);
1285 if (list_empty(&out->offload_cmd_list)) {
1286 ALOGV("%s SLEEPING", __func__);
1287 pthread_cond_wait(&out->offload_cond, &out->lock);
1288 ALOGV("%s RUNNING", __func__);
1289 continue;
1290 }
1291
1292 item = list_head(&out->offload_cmd_list);
1293 cmd = node_to_item(item, struct offload_cmd, node);
1294 list_remove(item);
1295
1296 ALOGVV("%s STATE %d CMD %d out->compr %p",
1297 __func__, out->offload_state, cmd->cmd, out->compr);
1298
1299 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1300 free(cmd);
1301 break;
1302 }
1303
1304 if (out->compr == NULL) {
1305 ALOGE("%s: Compress handle is NULL", __func__);
1306 pthread_cond_signal(&out->cond);
1307 continue;
1308 }
1309 out->offload_thread_blocked = true;
1310 pthread_mutex_unlock(&out->lock);
1311 send_callback = false;
1312 switch(cmd->cmd) {
1313 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Steve Kondik05c17962015-02-25 00:55:50 -08001314 ALOGV("copl(%x):calling compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001315 compress_wait(out->compr, -1);
Steve Kondik05c17962015-02-25 00:55:50 -08001316 ALOGV("copl(%x):out of compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001317 send_callback = true;
1318 event = STREAM_CBK_EVENT_WRITE_READY;
1319 break;
1320 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001321 ret = compress_next_track(out->compr);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301322 if(ret == 0) {
Steve Kondik05c17962015-02-25 00:55:50 -08001323 ALOGV("copl(%p):calling compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301324 ret = compress_partial_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001325 ALOGV("copl(%p):out of compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301326 if (ret < 0)
1327 ret = -errno;
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301328 }
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301329 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001330 compress_drain(out->compr);
1331 else
1332 ALOGE("%s: Next track returned error %d",__func__, ret);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301333
Alexy Joseph505da3f2015-09-10 01:31:51 -07001334 send_callback = true;
1335 event = STREAM_CBK_EVENT_DRAIN_READY;
1336 pthread_mutex_lock(&out->lock);
1337 /* Resend the metadata for next iteration */
1338 out->send_new_metadata = 1;
1339 out->send_next_track_params = true;
1340 pthread_mutex_unlock(&out->lock);
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 }
Alexy Joseph505da3f2015-09-10 01:31:51 -07001633 /* compress_open sends params of the track, so reset the flag here */
1634 out->is_compr_metadata_avail = false;
1635
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001636 if (out->offload_callback)
1637 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001638
Fred Oh1483d8a2015-03-04 18:42:34 -08001639 /* Since small bufs uses blocking writes, a write will be blocked
1640 for the default max poll time (20s) in the event of an SSR.
1641 Reduce the poll time to observe and deal with SSR faster.
1642 */
1643 if (out->use_small_bufs) {
1644 compress_set_max_poll_wait(out->compr, 1000);
1645 }
1646
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08001647#ifdef DS1_DOLBY_DDP_ENABLED
1648 if (audio_extn_is_dolby_format(out->format))
1649 audio_extn_dolby_send_ddp_endp_params(adev);
1650#endif
1651
Eric Laurentc4aef752013-09-12 17:45:53 -07001652 if (adev->visualizer_start_output != NULL)
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001653 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1654 if (adev->offload_effects_start_output != NULL)
1655 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001656 }
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001657 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001658 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001659 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001660error_open:
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001661 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001662 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001663error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001664 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001665}
1666
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001667static int check_input_parameters(uint32_t sample_rate,
1668 audio_format_t format,
1669 int channel_count)
1670{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001671 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001672
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001673 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001674 !voice_extn_compress_voip_is_format_supported(format) &&
1675 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001676
1677 switch (channel_count) {
1678 case 1:
1679 case 2:
1680 case 6:
1681 break;
1682 default:
1683 ret = -EINVAL;
1684 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001685
1686 switch (sample_rate) {
1687 case 8000:
1688 case 11025:
1689 case 12000:
1690 case 16000:
1691 case 22050:
1692 case 24000:
1693 case 32000:
1694 case 44100:
1695 case 48000:
1696 break;
1697 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001698 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001699 }
1700
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001701 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001702}
1703
1704static size_t get_input_buffer_size(uint32_t sample_rate,
1705 audio_format_t format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001706 int channel_count,
1707 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001708{
1709 size_t size = 0;
1710
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001711 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1712 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001713
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001714 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001715 if (is_low_latency)
1716 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001717 /* ToDo: should use frame_size computed based on the format and
1718 channel_count here. */
1719 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001721 /* make sure the size is multiple of 32 bytes
1722 * At 48 kHz mono 16-bit PCM:
1723 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1724 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1725 */
1726 size += 0x1f;
1727 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001728
1729 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001730}
1731
1732static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1733{
1734 struct stream_out *out = (struct stream_out *)stream;
1735
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001736 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001737}
1738
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301739static int out_set_sample_rate(struct audio_stream *stream __unused,
1740 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001741{
1742 return -ENOSYS;
1743}
1744
1745static size_t out_get_buffer_size(const struct audio_stream *stream)
1746{
1747 struct stream_out *out = (struct stream_out *)stream;
1748
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001749 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001750 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001751 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1752 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001753
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301754 return out->config.period_size *
1755 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001756}
1757
1758static uint32_t out_get_channels(const struct audio_stream *stream)
1759{
1760 struct stream_out *out = (struct stream_out *)stream;
1761
1762 return out->channel_mask;
1763}
1764
1765static audio_format_t out_get_format(const struct audio_stream *stream)
1766{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001767 struct stream_out *out = (struct stream_out *)stream;
1768
1769 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770}
1771
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301772static int out_set_format(struct audio_stream *stream __unused,
1773 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001774{
1775 return -ENOSYS;
1776}
1777
1778static int out_standby(struct audio_stream *stream)
1779{
1780 struct stream_out *out = (struct stream_out *)stream;
1781 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001782
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301783 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1784 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001785 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1786 /* Ignore standby in case of voip call because the voip output
1787 * stream is closed in adev_close_output_stream()
1788 */
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301789 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001790 return 0;
1791 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792
Eric Laurent35455462015-06-19 16:30:44 -07001793 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001795 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07001796
1797 amplifier_output_stream_standby((struct audio_stream_out *) stream);
1798
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001799 out->standby = true;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001800 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001801 if (out->pcm) {
1802 pcm_close(out->pcm);
1803 out->pcm = NULL;
1804 }
1805 } else {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301806 ALOGD("copl(%x):standby", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001807 stop_compressed_output_l(out);
Alexy Joseph505da3f2015-09-10 01:31:51 -07001808 out->send_next_track_params = false;
1809 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001810 out->gapless_mdata.encoder_delay = 0;
1811 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001812 if (out->compr != NULL) {
1813 compress_close(out->compr);
1814 out->compr = NULL;
1815 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001816 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001817 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001818 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001819 }
1820 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001821 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822 return 0;
1823}
1824
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301825static int out_dump(const struct audio_stream *stream __unused,
1826 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001827{
1828 return 0;
1829}
1830
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001831static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1832{
1833 int ret = 0;
1834 char value[32];
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001835
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001836 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001837 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001838 return -EINVAL;
1839 }
1840
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001841 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1842 if (ret >= 0) {
1843 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1844 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1845 ALOGV("ADTS format is set in offload mode");
1846 }
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001847 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001848 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1849 if (ret >= 0) {
Alexy Joseph505da3f2015-09-10 01:31:51 -07001850 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001851 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001852 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1853 if (ret >= 0) {
Alexy Joseph505da3f2015-09-10 01:31:51 -07001854 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001855 }
1856
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001857 ALOGV("%s new encoder delay %u and padding %u", __func__,
1858 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1859
1860 return 0;
1861}
1862
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301863static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1864{
1865 return out == adev->primary_output || out == adev->voice_tx_output;
1866}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001867
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001868static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1869{
1870 struct stream_out *out = (struct stream_out *)stream;
1871 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001872 struct audio_usecase *usecase;
1873 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001874 struct str_parms *parms;
1875 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001876 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001877 bool select_new_device = false;
Steve Kondik3abbbc82014-11-29 14:14:43 -08001878 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001879
sangwoobc677242013-08-08 16:53:43 +09001880 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001881 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001882 parms = str_parms_create_str(kvpairs);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001883 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1884 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001885 val = atoi(value);
Eric Laurent35455462015-06-19 16:30:44 -07001886 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001887 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001888
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001889 /*
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301890 * When HDMI cable is unplugged/usb hs is disconnected the
1891 * music playback is paused and the policy manager sends routing=0
1892 * But the audioflingercontinues to write data until standby time
1893 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001894 * Avoid this by routing audio to speaker until standby.
1895 */
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301896 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
Steve Kondikeadb6c82014-09-03 18:40:06 -07001897 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
1898 out->devices == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001899 val == AUDIO_DEVICE_NONE) {
1900 val = AUDIO_DEVICE_OUT_SPEAKER;
1901 }
1902
1903 /*
1904 * select_devices() call below switches all the usecases on the same
1905 * backend to the new device. Refer to check_usecases_codec_backend() in
1906 * the select_devices(). But how do we undo this?
1907 *
1908 * For example, music playback is active on headset (deep-buffer usecase)
1909 * and if we go to ringtones and select a ringtone, low-latency usecase
1910 * will be started on headset+speaker. As we can't enable headset+speaker
1911 * and headset devices at the same time, select_devices() switches the music
1912 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1913 * So when the ringtone playback is completed, how do we undo the same?
1914 *
1915 * We are relying on the out_set_parameters() call on deep-buffer output,
1916 * once the ringtone playback is ended.
1917 * NOTE: We should not check if the current devices are same as new devices.
1918 * Because select_devices() must be called to switch back the music
1919 * playback to headset.
1920 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001921 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001922 out->devices = val;
1923
1924 if (!out->standby)
1925 select_devices(adev, out->usecase);
1926
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001927 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301928 output_drives_call(adev, out)) {
1929 adev->current_call_output = out;
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001930 if (!adev->voice.in_call)
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301931 ret = voice_start_call(adev);
1932 else
1933 voice_update_devices_for_all_voice_usecases(adev);
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001934 }
1935 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001936
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001937 if ((adev->mode == AUDIO_MODE_NORMAL) &&
1938 adev->voice.in_call &&
1939 output_drives_call(adev, out)) {
1940 ret = voice_stop_call(adev);
1941 adev->current_call_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001942 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001943
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001944 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001945 pthread_mutex_unlock(&out->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05001946
1947 /*handles device and call state changes*/
1948 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001950
1951 if (out == adev->primary_output) {
1952 pthread_mutex_lock(&adev->lock);
1953 audio_extn_set_parameters(adev, parms);
1954 pthread_mutex_unlock(&adev->lock);
1955 }
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001956 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001957 pthread_mutex_lock(&out->lock);
Steve Kondikba3b35d2014-07-18 01:49:48 -07001958 ret = parse_compress_metadata(out, parms);
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001959 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001960 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001961
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001962 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08001963 ALOGV("%s: exit: code(%d)", __func__, status);
1964 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001965}
1966
1967static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1968{
1969 struct stream_out *out = (struct stream_out *)stream;
1970 struct str_parms *query = str_parms_create_str(keys);
1971 char *str;
1972 char value[256];
1973 struct str_parms *reply = str_parms_create();
1974 size_t i, j;
1975 int ret;
1976 bool first = true;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001977
1978 if (!query || !reply) {
1979 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1980 return NULL;
1981 }
1982
Eric Laurent994a6932013-07-17 11:51:42 -07001983 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001984 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1985 if (ret >= 0) {
1986 value[0] = '\0';
1987 i = 0;
1988 while (out->supported_channel_masks[i] != 0) {
1989 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
1990 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
1991 if (!first) {
1992 strcat(value, "|");
1993 }
1994 strcat(value, out_channels_name_to_enum_table[j].name);
1995 first = false;
1996 break;
1997 }
1998 }
1999 i++;
2000 }
2001 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2002 str = str_parms_to_str(reply);
2003 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002004 voice_extn_out_get_parameters(out, query, reply);
2005 str = str_parms_to_str(reply);
2006 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella2e032352014-01-29 12:52:19 -08002007 free(str);
2008 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002009 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002010 }
2011 str_parms_destroy(query);
2012 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002013 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002014 return str;
2015}
2016
2017static uint32_t out_get_latency(const struct audio_stream_out *stream)
2018{
2019 struct stream_out *out = (struct stream_out *)stream;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002020 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002021
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002022 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002023 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002024 } else {
2025 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002026 (out->config.rate);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002027 }
2028
Anish Kumar1a0594f2014-12-09 04:01:39 +05302029 ALOGV("%s: Latency %d", __func__, latency);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002030 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002031}
2032
2033static int out_set_volume(struct audio_stream_out *stream, float left,
2034 float right)
2035{
Eric Laurenta9024de2013-04-04 09:19:12 -07002036 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002037 int volume[2];
2038
Eric Laurenta9024de2013-04-04 09:19:12 -07002039 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2040 /* only take left channel into account: the API is for stereo anyway */
2041 out->muted = (left == 0.0f);
2042 return 0;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002043 } else if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002044 char mixer_ctl_name[128];
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002045 struct audio_device *adev = out->dev;
2046 struct mixer_ctl *ctl;
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002047 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2048 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002049
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002050 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2051 "Compress Playback %d Volume", pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002052 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2053 if (!ctl) {
2054 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2055 __func__, mixer_ctl_name);
2056 return -EINVAL;
2057 }
2058 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2059 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2060 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2061 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002062 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002064 return -ENOSYS;
2065}
2066
2067static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2068 size_t bytes)
2069{
2070 struct stream_out *out = (struct stream_out *)stream;
2071 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302072 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002073 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002074
Eric Laurent35455462015-06-19 16:30:44 -07002075 lock_output_stream(out);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302076
Naresh Tannirucef332d2014-06-04 18:17:56 +05302077 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
2078 if (out->pcm) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302079 ALOGD(" %s: sound card is not active/SSR state", __func__);
2080 ret= -ENETRESET;
2081 goto exit;
Alexy Joseph55204352014-10-06 12:15:01 -07002082 } else if (is_offload_usecase(out->usecase)) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302083 //during SSR for compress usecase we should return error to flinger
2084 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2085 pthread_mutex_unlock(&out->lock);
2086 return -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302087 }
2088 }
2089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002090 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002091 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002092 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002093 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2094 ret = voice_extn_compress_voip_start_output_stream(out);
2095 else
2096 ret = start_output_stream(out);
Ethan Chen79c356c2015-06-07 12:26:14 -07002097
2098 if (ret == 0)
2099 amplifier_output_stream_start(stream,
2100 is_offload_usecase(out->usecase));
2101
Eric Laurent150dbfe2013-02-27 14:31:02 -08002102 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002103 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002104 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002105 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002106 goto exit;
2107 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002108 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002109
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002110 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002111 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002112 if (out->send_new_metadata) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302113 ALOGD("copl(%x):send new gapless metadata", (unsigned int)out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002114 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2115 out->send_new_metadata = 0;
Alexy Joseph505da3f2015-09-10 01:31:51 -07002116 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2117 ALOGD("copl(%p):send next track params in gapless", out);
2118 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2119 out->send_next_track_params = false;
2120 out->is_compr_metadata_avail = false;
2121 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002122 }
2123
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002124 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302125 if (ret < 0)
2126 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002127 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002128 if (ret >= 0 && ret < (ssize_t)bytes) {
Steve Kondik32c2e312016-02-14 11:40:38 -08002129 ALOGV("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002130 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302131 } else if (-ENETRESET == ret) {
2132 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2133 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2134 pthread_mutex_unlock(&out->lock);
2135 out_standby(&out->stream.common);
2136 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002137 }
Naresh Tannirucef332d2014-06-04 18:17:56 +05302138 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002139 compress_start(out->compr);
2140 out->playback_started = 1;
2141 out->offload_state = OFFLOAD_STATE_PLAYING;
2142 }
2143 pthread_mutex_unlock(&out->lock);
2144 return ret;
2145 } else {
2146 if (out->pcm) {
2147 if (out->muted)
2148 memset((void *)buffer, 0, bytes);
2149 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302150 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2151 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2152 else
2153 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302154 if (ret < 0)
2155 ret = -errno;
2156 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002157 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002158 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002159 }
2160
2161exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302162 /* ToDo: There may be a corner case when SSR happens back to back during
2163 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302164 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302165 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302166 }
2167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002168 pthread_mutex_unlock(&out->lock);
2169
2170 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002171 if (out->pcm)
2172 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302173 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302174 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302175 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302176 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302177 out->standby = true;
2178 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002179 out_standby(&out->stream.common);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002180 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
2181 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002182 }
2183 return bytes;
2184}
2185
2186static int out_get_render_position(const struct audio_stream_out *stream,
2187 uint32_t *dsp_frames)
2188{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002189 struct stream_out *out = (struct stream_out *)stream;
Amit Shekharfaefb322014-09-08 14:08:19 -07002190
2191 if (dsp_frames == NULL)
2192 return -EINVAL;
2193
2194 *dsp_frames = 0;
2195 if (is_offload_usecase(out->usecase)) {
2196 ssize_t ret = 0;
Eric Laurent35455462015-06-19 16:30:44 -07002197 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002198 if (out->compr != NULL) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302199 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002200 &out->sample_rate);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302201 if (ret < 0)
2202 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002203 ALOGVV("%s rendered frames %d sample_rate %d",
2204 __func__, *dsp_frames, out->sample_rate);
2205 }
2206 pthread_mutex_unlock(&out->lock);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302207 if (-ENETRESET == ret) {
2208 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2209 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2210 return -EINVAL;
2211 } else if(ret < 0) {
Steve Kondik81506242014-07-21 16:12:57 -07002212 ALOGE(" ERROR: Unable to get time stamp from compress driver ret=%d", ret);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302213 return -EINVAL;
2214 } else {
2215 return 0;
2216 }
Amit Shekharfaefb322014-09-08 14:08:19 -07002217 } else if (audio_is_linear_pcm(out->format)) {
2218 *dsp_frames = out->written;
2219 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002220 } else
2221 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002222}
2223
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302224static int out_add_audio_effect(const struct audio_stream *stream __unused,
2225 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002226{
2227 return 0;
2228}
2229
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302230static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2231 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002232{
2233 return 0;
2234}
2235
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302236static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2237 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238{
2239 return -EINVAL;
2240}
2241
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002242static int out_get_presentation_position(const struct audio_stream_out *stream,
2243 uint64_t *frames, struct timespec *timestamp)
2244{
2245 struct stream_out *out = (struct stream_out *)stream;
2246 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002247 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002248
Eric Laurent35455462015-06-19 16:30:44 -07002249 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002250
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002251 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002252 if (out->compr != NULL) {
2253 compress_get_tstamp(out->compr, &dsp_frames,
2254 &out->sample_rate);
2255 ALOGVV("%s rendered frames %ld sample_rate %d",
2256 __func__, dsp_frames, out->sample_rate);
2257 *frames = dsp_frames;
2258 ret = 0;
2259 /* this is the best we can do */
2260 clock_gettime(CLOCK_MONOTONIC, timestamp);
2261 }
2262 } else {
2263 if (out->pcm) {
2264 size_t avail;
2265 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2266 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002267 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002268 // This adjustment accounts for buffering after app processor.
2269 // It is based on estimated DSP latency per use case, rather than exact.
2270 signed_frames -=
2271 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2272
Eric Laurent949a0892013-09-20 09:20:13 -07002273 // It would be unusual for this value to be negative, but check just in case ...
2274 if (signed_frames >= 0) {
2275 *frames = signed_frames;
2276 ret = 0;
2277 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002278 }
2279 }
2280 }
2281
2282 pthread_mutex_unlock(&out->lock);
2283
2284 return ret;
2285}
2286
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002287static int out_set_callback(struct audio_stream_out *stream,
2288 stream_callback_t callback, void *cookie)
2289{
2290 struct stream_out *out = (struct stream_out *)stream;
2291
2292 ALOGV("%s", __func__);
Eric Laurent35455462015-06-19 16:30:44 -07002293 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002294 out->offload_callback = callback;
2295 out->offload_cookie = cookie;
2296 pthread_mutex_unlock(&out->lock);
2297 return 0;
2298}
2299
2300static int out_pause(struct audio_stream_out* stream)
2301{
2302 struct stream_out *out = (struct stream_out *)stream;
2303 int status = -ENOSYS;
2304 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002305 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302306 ALOGD("copl(%x):pause compress driver", (unsigned int)out);
Eric Laurent35455462015-06-19 16:30:44 -07002307 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002308 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302309 struct audio_device *adev = out->dev;
2310 int snd_scard_state = get_snd_card_state(adev);
2311
2312 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2313 status = compress_pause(out->compr);
2314
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002315 out->offload_state = OFFLOAD_STATE_PAUSED;
2316 }
2317 pthread_mutex_unlock(&out->lock);
2318 }
2319 return status;
2320}
2321
2322static int out_resume(struct audio_stream_out* stream)
2323{
2324 struct stream_out *out = (struct stream_out *)stream;
2325 int status = -ENOSYS;
2326 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002327 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302328 ALOGD("copl(%x):resume compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002329 status = 0;
Eric Laurent35455462015-06-19 16:30:44 -07002330 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002331 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302332 struct audio_device *adev = out->dev;
2333 int snd_scard_state = get_snd_card_state(adev);
2334
2335 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2336 status = compress_resume(out->compr);
2337
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002338 out->offload_state = OFFLOAD_STATE_PLAYING;
2339 }
2340 pthread_mutex_unlock(&out->lock);
2341 }
2342 return status;
2343}
2344
2345static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2346{
2347 struct stream_out *out = (struct stream_out *)stream;
2348 int status = -ENOSYS;
2349 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002350 if (is_offload_usecase(out->usecase)) {
Eric Laurent35455462015-06-19 16:30:44 -07002351 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002352 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2353 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2354 else
2355 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2356 pthread_mutex_unlock(&out->lock);
2357 }
2358 return status;
2359}
2360
2361static int out_flush(struct audio_stream_out* stream)
2362{
2363 struct stream_out *out = (struct stream_out *)stream;
2364 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002365 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302366 ALOGD("copl(%x):calling compress flush", (unsigned int)out);
Eric Laurent35455462015-06-19 16:30:44 -07002367 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002368 stop_compressed_output_l(out);
2369 pthread_mutex_unlock(&out->lock);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302370 ALOGD("copl(%x):out of compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002371 return 0;
2372 }
2373 return -ENOSYS;
2374}
2375
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002376/** audio_stream_in implementation **/
2377static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2378{
2379 struct stream_in *in = (struct stream_in *)stream;
2380
2381 return in->config.rate;
2382}
2383
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302384static int in_set_sample_rate(struct audio_stream *stream __unused,
2385 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002386{
2387 return -ENOSYS;
2388}
2389
2390static size_t in_get_buffer_size(const struct audio_stream *stream)
2391{
2392 struct stream_in *in = (struct stream_in *)stream;
2393
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002394 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2395 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002396 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2397 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002398
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302399 return in->config.period_size *
Steve Kondik3abbbc82014-11-29 14:14:43 -08002400 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002401}
2402
2403static uint32_t in_get_channels(const struct audio_stream *stream)
2404{
2405 struct stream_in *in = (struct stream_in *)stream;
2406
2407 return in->channel_mask;
2408}
2409
2410static audio_format_t in_get_format(const struct audio_stream *stream)
2411{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002412 struct stream_in *in = (struct stream_in *)stream;
2413
2414 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002415}
2416
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302417static int in_set_format(struct audio_stream *stream __unused,
2418 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002419{
2420 return -ENOSYS;
2421}
2422
2423static int in_standby(struct audio_stream *stream)
2424{
2425 struct stream_in *in = (struct stream_in *)stream;
2426 struct audio_device *adev = in->dev;
2427 int status = 0;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302428 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2429 stream, in->usecase, use_case_table[in->usecase]);
2430
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002431 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2432 /* Ignore standby in case of voip call because the voip input
2433 * stream is closed in adev_close_input_stream()
2434 */
2435 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2436 return status;
2437 }
2438
Eric Laurent35455462015-06-19 16:30:44 -07002439 lock_input_stream(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002440 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002441 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07002442
2443 amplifier_input_stream_standby((struct audio_stream_in *) stream);
2444
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002446 if (in->pcm) {
2447 pcm_close(in->pcm);
2448 in->pcm = NULL;
2449 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002450 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002451 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452 }
2453 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002454 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455 return status;
2456}
2457
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302458static int in_dump(const struct audio_stream *stream __unused,
2459 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460{
2461 return 0;
2462}
2463
2464static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2465{
2466 struct stream_in *in = (struct stream_in *)stream;
2467 struct audio_device *adev = in->dev;
2468 struct str_parms *parms;
2469 char *str;
2470 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002471 int ret = 0, val = 0, err;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002472 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002473
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302474 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002475 parms = str_parms_create_str(kvpairs);
2476
Eric Laurent35455462015-06-19 16:30:44 -07002477 lock_input_stream(in);
2478
Eric Laurent150dbfe2013-02-27 14:31:02 -08002479 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002480
2481 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2482 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002483 val = atoi(value);
2484 /* no audio source uses val == 0 */
2485 if ((in->source != val) && (val != 0)) {
2486 in->source = val;
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002487 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2488 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2489 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2490 (in->config.rate == 8000 || in->config.rate == 16000) &&
Steve Kondikb6ab1fa2015-02-06 16:55:26 -08002491 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002492 err = voice_extn_compress_voip_open_input_stream(in);
2493 if (err != 0) {
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002494 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002495 __func__, err);
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002496 }
2497 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002498 }
2499 }
2500
Steve Kondik3abbbc82014-11-29 14:14:43 -08002501 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2502
2503 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002504 val = atoi(value);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302505 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002506 in->device = val;
2507 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002508 if (!in->standby)
Steve Kondik3abbbc82014-11-29 14:14:43 -08002509 status = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 }
2511 }
2512
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002513done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002514 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002515 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516
2517 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002518 ALOGV("%s: exit: status(%d)", __func__, status);
2519 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002520}
2521
2522static char* in_get_parameters(const struct audio_stream *stream,
2523 const char *keys)
2524{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002525 struct stream_in *in = (struct stream_in *)stream;
2526 struct str_parms *query = str_parms_create_str(keys);
2527 char *str;
2528 char value[256];
2529 struct str_parms *reply = str_parms_create();
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002530
2531 if (!query || !reply) {
2532 ALOGE("in_get_parameters: failed to create query or reply");
2533 return NULL;
2534 }
2535
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002536 ALOGV("%s: enter: keys - %s", __func__, keys);
2537
2538 voice_extn_in_get_parameters(in, query, reply);
2539
2540 str = str_parms_to_str(reply);
2541 str_parms_destroy(query);
2542 str_parms_destroy(reply);
2543
2544 ALOGV("%s: exit: returns - %s", __func__, str);
2545 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002546}
2547
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302548static int in_set_gain(struct audio_stream_in *stream __unused,
2549 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002550{
2551 return 0;
2552}
2553
2554static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2555 size_t bytes)
2556{
2557 struct stream_in *in = (struct stream_in *)stream;
2558 struct audio_device *adev = in->dev;
2559 int i, ret = -1;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302560 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561
Eric Laurent35455462015-06-19 16:30:44 -07002562 lock_input_stream(in);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302563
2564 if (in->pcm) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302565 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302566 ALOGD(" %s: sound card is not active/SSR state", __func__);
2567 ret= -ENETRESET;
2568 goto exit;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302569 }
2570 }
2571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002573 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002574 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2575 ret = voice_extn_compress_voip_start_input_stream(in);
2576 else
2577 ret = start_input_stream(in);
Ethan Chen79c356c2015-06-07 12:26:14 -07002578
2579 if (ret == 0)
2580 amplifier_input_stream_start(stream);
2581
Eric Laurent150dbfe2013-02-27 14:31:02 -08002582 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 goto exit;
2585 }
2586 in->standby = 0;
2587 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002588
2589 if (in->pcm) {
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302590 if (audio_extn_ssr_get_enabled() &&
2591 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002592 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002593 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2594 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302595 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2596 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002597 else
2598 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302599 if (ret < 0)
2600 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002601 }
2602
2603 /*
2604 * Instead of writing zeroes here, we could trust the hardware
2605 * to always provide zeroes when muted.
2606 */
Pavan Chikkala6c183fd2014-12-04 10:48:28 +05302607 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2608 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 memset(buffer, 0, bytes);
2610
2611exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302612 /* ToDo: There may be a corner case when SSR happens back to back during
2613 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302614 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302615 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302616 memset(buffer, 0, bytes);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302617 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 pthread_mutex_unlock(&in->lock);
2619
2620 if (ret != 0) {
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302621 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302622 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302623 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302624 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302625 in->standby = true;
2626 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002627 in_standby(&in->stream.common);
2628 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002629 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
2630 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002631 }
2632 return bytes;
2633}
2634
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302635static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002636{
2637 return 0;
2638}
2639
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002640static int add_remove_audio_effect(const struct audio_stream *stream,
2641 effect_handle_t effect,
2642 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002643{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002644 struct stream_in *in = (struct stream_in *)stream;
2645 int status = 0;
2646 effect_descriptor_t desc;
2647
2648 status = (*effect)->get_descriptor(effect, &desc);
2649 if (status != 0)
2650 return status;
2651
Eric Laurent35455462015-06-19 16:30:44 -07002652 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002653 pthread_mutex_lock(&in->dev->lock);
2654 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2655 in->enable_aec != enable &&
2656 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2657 in->enable_aec = enable;
2658 if (!in->standby)
2659 select_devices(in->dev, in->usecase);
2660 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002661 if (in->enable_ns != enable &&
2662 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2663 in->enable_ns = enable;
2664 if (!in->standby)
2665 select_devices(in->dev, in->usecase);
2666 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002667 pthread_mutex_unlock(&in->dev->lock);
2668 pthread_mutex_unlock(&in->lock);
2669
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670 return 0;
2671}
2672
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002673static int in_add_audio_effect(const struct audio_stream *stream,
2674 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002675{
Eric Laurent994a6932013-07-17 11:51:42 -07002676 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002677 return add_remove_audio_effect(stream, effect, true);
2678}
2679
2680static int in_remove_audio_effect(const struct audio_stream *stream,
2681 effect_handle_t effect)
2682{
Eric Laurent994a6932013-07-17 11:51:42 -07002683 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002684 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685}
2686
2687static int adev_open_output_stream(struct audio_hw_device *dev,
2688 audio_io_handle_t handle,
2689 audio_devices_t devices,
2690 audio_output_flags_t flags,
2691 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302692 struct audio_stream_out **stream_out,
2693 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002694{
2695 struct audio_device *adev = (struct audio_device *)dev;
2696 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002697 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 *stream_out = NULL;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302700
2701 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2702 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehtac2711cd2015-08-26 14:01:20 -07002703 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tannirucef332d2014-06-04 18:17:56 +05302704 return -EINVAL;
2705 }
2706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2708
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302709 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2710 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2711 devices, flags, &out->stream);
2712
2713
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002714 if (!out) {
2715 return -ENOMEM;
2716 }
2717
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718 if (devices == AUDIO_DEVICE_NONE)
2719 devices = AUDIO_DEVICE_OUT_SPEAKER;
2720
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002721 out->flags = flags;
2722 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002723 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002724 out->format = config->format;
2725 out->sample_rate = config->sample_rate;
2726 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2727 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002728 out->handle = handle;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002729 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002730 out->non_blocking = 0;
2731 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002732
2733 /* Init use case and pcm_config */
Mingming Yin8cde13d2015-07-21 15:22:22 -07002734 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2735 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Mingming Yinee733602014-04-03 17:47:22 -07002736 (
2737#ifdef AFE_PROXY_ENABLED
2738 out->devices & AUDIO_DEVICE_OUT_PROXY ||
2739#endif
2740 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002741
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002742 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002743 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2744 ret = read_hdmi_channel_masks(out);
2745
Mingming Yinee733602014-04-03 17:47:22 -07002746#ifdef AFE_PROXY_ENABLED
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002747 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2748 ret = audio_extn_read_afe_proxy_channel_masks(out);
Mingming Yinee733602014-04-03 17:47:22 -07002749#endif
2750
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002751 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002752 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002753 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002754
2755 if (config->sample_rate == 0)
2756 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2757 if (config->channel_mask == 0)
2758 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2759
2760 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002761 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2763 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764 out->config.rate = config->sample_rate;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302765 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002766 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Mingming Yinee733602014-04-03 17:47:22 -07002767#ifdef COMPRESS_VOIP_ENABLED
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002768 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Scott Mertz624f14f2016-04-05 12:40:11 -07002769 ((out->flags & ~AUDIO_OUTPUT_FLAG_RAW) ==
2770 (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002771 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002772 ret = voice_extn_compress_voip_open_output_stream(out);
2773 if (ret != 0) {
2774 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2775 __func__, ret);
2776 goto error_open;
2777 }
Mingming Yinee733602014-04-03 17:47:22 -07002778#endif
vivek mehtac2711cd2015-08-26 14:01:20 -07002779 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2780 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302781 ALOGD("%s: copl(%x): sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
2782 __func__, (unsigned int)out, config->sample_rate, config->channel_mask, devices, flags);
2783
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002784 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2785 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2786 ALOGE("%s: Unsupported Offload information", __func__);
2787 ret = -EINVAL;
2788 goto error_open;
2789 }
Mingming Yin90310102013-11-13 16:57:00 -08002790 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002791 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehtac2711cd2015-08-26 14:01:20 -07002792 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002793 ret = -EINVAL;
2794 goto error_open;
2795 }
2796
2797 out->compr_config.codec = (struct snd_codec *)
2798 calloc(1, sizeof(struct snd_codec));
2799
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002800 if (!out->compr_config.codec) {
2801 ret = -ENOMEM;
2802 goto error_open;
2803 }
2804
vivek mehtac2711cd2015-08-26 14:01:20 -07002805 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2806 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2807 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2808 } else {
2809 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2810 out->usecase = get_offload_usecase(adev);
Amit Shekharfaefb322014-09-08 14:08:19 -07002811
2812 out->stream.set_callback = out_set_callback;
2813 out->stream.pause = out_pause;
2814 out->stream.resume = out_resume;
2815 out->stream.drain = out_drain;
2816 out->stream.flush = out_flush;
vivek mehtac2711cd2015-08-26 14:01:20 -07002817 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818 if (config->offload_info.channel_mask)
2819 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002820 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821 out->channel_mask = config->channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002822 config->offload_info.channel_mask = config->channel_mask;
2823 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002824 out->format = config->offload_info.format;
2825 out->sample_rate = config->offload_info.sample_rate;
2826
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002827 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002828
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002829 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002830 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002831 audio_extn_dolby_get_snd_codec_id(adev, out,
2832 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002833 else
2834 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002835 get_snd_codec_id(config->offload_info.format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002836
vivek mehtac2711cd2015-08-26 14:01:20 -07002837 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2838 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002839 out->compr_config.fragment_size =
2840 platform_get_pcm_offload_buffer_size(&config->offload_info);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002841 } else {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002842 out->compr_config.fragment_size =
2843 platform_get_compress_offload_buffer_size(&config->offload_info);
2844 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002845 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0043e152014-10-23 14:42:59 -07002846#ifdef NEW_SAMPLE_RATE_ENABLED
2847 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
2848#else
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002849 out->compr_config.codec->sample_rate =
2850 compress_get_alsa_rate(config->offload_info.sample_rate);
Eric Laurent0043e152014-10-23 14:42:59 -07002851#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002852 out->compr_config.codec->bit_rate =
2853 config->offload_info.bit_rate;
2854 out->compr_config.codec->ch_in =
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302855 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002856 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Amit Shekharfaefb322014-09-08 14:08:19 -07002857 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
2858 /*TODO: Do we need to change it for passthrough */
2859 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002861 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
Steve Kondik37454012014-11-23 19:54:21 -08002862 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002863 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2864 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002865 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002866 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehtac2711cd2015-08-26 14:01:20 -07002867 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
2868 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002869
Steve Kondik3abbbc82014-11-29 14:14:43 -08002870 if (out->bit_width == 24)
2871 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002872
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002873#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik37454012014-11-23 19:54:21 -08002874 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Amit Shekharfaefb322014-09-08 14:08:19 -07002875 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002876#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002877
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002878 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2879 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002880
Mingming Yind48310a2015-06-10 16:28:10 -07002881 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002882 //this flag is set from framework only if its for PCM formats
2883 //no need to check for PCM format again
2884 out->non_blocking = 0;
2885 out->use_small_bufs = true;
2886 ALOGI("Keep write blocking for small buff: non_blockling %d",
2887 out->non_blocking);
2888 }
2889
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002890 out->send_new_metadata = 1;
Alexy Joseph505da3f2015-09-10 01:31:51 -07002891 out->send_next_track_params = false;
2892 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002893 out->offload_state = OFFLOAD_STATE_IDLE;
2894 out->playback_started = 0;
2895
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002896 create_offload_callback_thread(out);
2897 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2898 __func__, config->offload_info.version,
2899 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002900 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -08002901 check_and_set_gapless_mode(adev);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002902
Mingming Yinee733602014-04-03 17:47:22 -07002903#ifdef INCALL_MUSIC_ENABLED
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002904 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2905 ret = voice_check_and_set_incall_music_usecase(adev, out);
2906 if (ret != 0) {
2907 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2908 __func__, ret);
2909 goto error_open;
2910 }
Mingming Yinee733602014-04-03 17:47:22 -07002911#endif
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302912 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2913 if (config->sample_rate == 0)
2914 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2915 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2916 config->sample_rate != 8000) {
2917 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2918 ret = -EINVAL;
2919 goto error_open;
2920 }
2921 out->sample_rate = config->sample_rate;
2922 out->config.rate = config->sample_rate;
2923 if (config->format == AUDIO_FORMAT_DEFAULT)
2924 config->format = AUDIO_FORMAT_PCM_16_BIT;
2925 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2926 config->format = AUDIO_FORMAT_PCM_16_BIT;
2927 ret = -EINVAL;
2928 goto error_open;
2929 }
2930 out->format = config->format;
2931 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2932 out->config = pcm_config_afe_proxy_playback;
2933 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002934 } else {
Steve Kondik26d44522015-12-16 15:23:47 -05002935 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2936 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2937 out->config = pcm_config_deep_buffer;
2938 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda8c884872015-06-25 20:08:01 -07002939 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2940 out->config = pcm_config_low_latency;
Amit Shekharfaefb322014-09-08 14:08:19 -07002941 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
2942 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2943 out->config = pcm_config_low_latency;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002944 } else {
2945 /* primary path is the default path selected if no other outputs are available/suitable */
2946 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Amit Shekharfaefb322014-09-08 14:08:19 -07002947 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002948 }
Amit Shekharfaefb322014-09-08 14:08:19 -07002949
Steve Kondik3abbbc82014-11-29 14:14:43 -08002950 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2951 if (k_enable_extended_precision
2952 && pcm_params_format_test(adev->use_case_table[out->usecase],
2953 pcm_format_from_audio_format(config->format))) {
2954 out->config.format = pcm_format_from_audio_format(config->format);
2955 /* out->format already set to config->format */
2956 } else {
2957 /* deny the externally proposed config format
2958 * and use the one specified in audio_hw layer configuration.
2959 * Note: out->format is returned by out->stream.common.get_format()
2960 * and is used to set config->format in the code several lines below.
2961 */
Steve Kondik5a447012014-12-02 16:04:20 -08002962 ALOGW("Audio format %x is not available on this output", out->format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002963 out->format = audio_format_from_pcm_format(out->config.format);
2964 }
2965 }
2966
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002967 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002968 }
2969
Amit Shekharfaefb322014-09-08 14:08:19 -07002970 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
2971 __func__, devices, flags, out->format, out->sample_rate, out->bit_width);
Steve Kondik5a447012014-12-02 16:04:20 -08002972
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002973 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
Steve Kondik3abbbc82014-11-29 14:14:43 -08002974 flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08002975 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002976 if(adev->primary_output == NULL)
2977 adev->primary_output = out;
2978 else {
2979 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002980 ret = -EEXIST;
2981 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002982 }
2983 }
2984
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985 /* Check if this usecase is already existing */
2986 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella0d06c8e2014-04-17 20:00:41 -07002987 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
2988 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002989 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002991 ret = -EEXIST;
2992 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002993 }
2994 pthread_mutex_unlock(&adev->lock);
2995
2996 out->stream.common.get_sample_rate = out_get_sample_rate;
2997 out->stream.common.set_sample_rate = out_set_sample_rate;
2998 out->stream.common.get_buffer_size = out_get_buffer_size;
2999 out->stream.common.get_channels = out_get_channels;
3000 out->stream.common.get_format = out_get_format;
3001 out->stream.common.set_format = out_set_format;
3002 out->stream.common.standby = out_standby;
3003 out->stream.common.dump = out_dump;
3004 out->stream.common.set_parameters = out_set_parameters;
3005 out->stream.common.get_parameters = out_get_parameters;
3006 out->stream.common.add_audio_effect = out_add_audio_effect;
3007 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3008 out->stream.get_latency = out_get_latency;
3009 out->stream.set_volume = out_set_volume;
3010 out->stream.write = out_write;
3011 out->stream.get_render_position = out_get_render_position;
3012 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003013 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003015 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003016 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003017 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003018
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303019 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurent35455462015-06-19 16:30:44 -07003020 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303021 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 config->format = out->stream.common.get_format(&out->stream.common);
3024 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3025 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3026
3027 *stream_out = &out->stream;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303028 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehtac2711cd2015-08-26 14:01:20 -07003029 use_case_table[out->usecase]);
3030
Eric Laurent994a6932013-07-17 11:51:42 -07003031 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003032 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003033
3034error_open:
3035 free(out);
3036 *stream_out = NULL;
3037 ALOGD("%s: exit: ret %d", __func__, ret);
3038 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003039}
3040
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303041static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003042 struct audio_stream_out *stream)
3043{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003044 struct stream_out *out = (struct stream_out *)stream;
3045 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003046 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303048 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3049
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003050 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303051 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003052 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303053 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003054 if(ret != 0)
3055 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3056 __func__, ret);
3057 }
3058 else
3059 out_standby(&stream->common);
3060
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003061 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003062 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003063 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003064 if (out->compr_config.codec != NULL)
3065 free(out->compr_config.codec);
3066 }
3067 pthread_cond_destroy(&out->cond);
3068 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003070 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003071}
3072
Alexy Joseph55204352014-10-06 12:15:01 -07003073static void close_compress_sessions(struct audio_device *adev)
3074{
3075 struct stream_out *out = NULL;
3076 struct listnode *node = NULL;
3077 struct listnode *tmp = NULL;
3078 struct audio_usecase *usecase = NULL;
3079 pthread_mutex_lock(&adev->lock);
3080 list_for_each_safe(node, tmp, &adev->usecase_list) {
3081 usecase = node_to_item(node, struct audio_usecase, list);
3082 if (is_offload_usecase(usecase->id)) {
3083 if (usecase && usecase->stream.out) {
3084 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3085 out = usecase->stream.out;
3086 pthread_mutex_unlock(&adev->lock);
3087 out_standby(&out->stream.common);
3088 pthread_mutex_lock(&adev->lock);
3089 }
3090 }
3091 }
3092 pthread_mutex_unlock(&adev->lock);
3093}
3094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3096{
3097 struct audio_device *adev = (struct audio_device *)dev;
3098 struct str_parms *parms;
3099 char *str;
3100 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003101 int val;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303102 int ret;
3103 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003104
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003105 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003107
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303108 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3109 if (ret >= 0) {
3110 char *snd_card_status = value+2;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303111 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05303112 struct listnode *node;
3113 struct audio_usecase *usecase;
3114
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303115 ALOGD("Received sound card OFFLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303116 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3117
Alexy Joseph55204352014-10-06 12:15:01 -07003118 //close compress sessions on OFFLINE status
3119 close_compress_sessions(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303120 } else if (strstr(snd_card_status, "ONLINE")) {
3121 ALOGD("Received sound card ONLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303122 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303123 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303124 }
3125
3126 pthread_mutex_lock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303127 status = voice_set_parameters(adev, parms);
3128 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003129 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003130
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303131 status = platform_set_parameters(adev->platform, parms);
3132 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003133 goto done;
3134
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303135 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3136 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003137 /* When set to false, HAL should disable EC and NS
3138 * But it is currently not supported.
3139 */
3140 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3141 adev->bluetooth_nrec = true;
3142 else
3143 adev->bluetooth_nrec = false;
3144 }
3145
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303146 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3147 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003148 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3149 adev->screen_off = false;
3150 else
3151 adev->screen_off = true;
3152 }
3153
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303154 ret = str_parms_get_int(parms, "rotation", &val);
3155 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003156 bool reverse_speakers = false;
3157 switch(val) {
3158 // FIXME: note that the code below assumes that the speakers are in the correct placement
3159 // relative to the user when the device is rotated 90deg from its default rotation. This
3160 // assumption is device-specific, not platform-specific like this code.
3161 case 270:
3162 reverse_speakers = true;
3163 break;
3164 case 0:
3165 case 90:
3166 case 180:
3167 break;
3168 default:
3169 ALOGE("%s: unexpected rotation of %d", __func__, val);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303170 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003171 }
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303172 if (status == 0) {
3173 if (adev->speaker_lr_swap != reverse_speakers) {
3174 adev->speaker_lr_swap = reverse_speakers;
3175 // only update the selected device if there is active pcm playback
3176 struct audio_usecase *usecase;
3177 struct listnode *node;
3178 list_for_each(node, &adev->usecase_list) {
3179 usecase = node_to_item(node, struct audio_usecase, list);
3180 if (usecase->type == PCM_PLAYBACK) {
Steve Kondik3abbbc82014-11-29 14:14:43 -08003181 status = select_devices(adev, usecase->id);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303182 break;
3183 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003184 }
3185 }
3186 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003187 }
3188
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003189 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003190
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003191done:
3192 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003193 pthread_mutex_unlock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303194 ALOGV("%s: exit with code(%d)", __func__, status);
3195 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003196}
3197
3198static char* adev_get_parameters(const struct audio_hw_device *dev,
3199 const char *keys)
3200{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003201 struct audio_device *adev = (struct audio_device *)dev;
3202 struct str_parms *reply = str_parms_create();
3203 struct str_parms *query = str_parms_create_str(keys);
3204 char *str;
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303205 char value[256] = {0};
3206 int ret = 0;
3207
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003208 if (!query || !reply) {
3209 ALOGE("adev_get_parameters: failed to create query or reply");
3210 return NULL;
3211 }
3212
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303213 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
3214 sizeof(value));
3215 if (ret >=0) {
3216 int val = 1;
3217 pthread_mutex_lock(&adev->snd_card_status.lock);
3218 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3219 val = 0;
3220 pthread_mutex_unlock(&adev->snd_card_status.lock);
3221 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, val);
3222 goto exit;
3223 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003224
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003225 pthread_mutex_lock(&adev->lock);
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303226
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003227 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003228 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003229 platform_get_parameters(adev->platform, query, reply);
Naresh Tannirucef332d2014-06-04 18:17:56 +05303230 pthread_mutex_unlock(&adev->lock);
3231
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303232exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003233 str = str_parms_to_str(reply);
3234 str_parms_destroy(query);
3235 str_parms_destroy(reply);
3236
3237 ALOGV("%s: exit: returns - %s", __func__, str);
3238 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003239}
3240
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303241static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003242{
3243 return 0;
3244}
3245
3246static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3247{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003248 int ret;
3249 struct audio_device *adev = (struct audio_device *)dev;
Eric Laurent321b96d2014-09-10 13:21:01 -05003250
3251 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3252
Haynes Mathew George5191a852013-09-11 14:19:36 -07003253 pthread_mutex_lock(&adev->lock);
3254 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003255 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003256 pthread_mutex_unlock(&adev->lock);
3257 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003258}
3259
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303260static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3261 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003262{
3263 return -ENOSYS;
3264}
3265
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303266static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3267 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003268{
3269 return -ENOSYS;
3270}
3271
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303272static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3273 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003274{
3275 return -ENOSYS;
3276}
3277
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303278static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3279 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003280{
3281 return -ENOSYS;
3282}
3283
3284static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3285{
3286 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 pthread_mutex_lock(&adev->lock);
3288 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003289 ALOGD("%s mode %d\n", __func__, mode);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303290 if (amplifier_set_mode(mode) != 0)
3291 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 adev->mode = mode;
3293 }
3294 pthread_mutex_unlock(&adev->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003295
3296 audio_extn_extspk_set_mode(adev->extspk, mode);
3297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 return 0;
3299}
3300
3301static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3302{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003303 int ret;
3304
3305 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003306 ALOGD("%s state %d\n", __func__, state);
Shreyas Nagasandra Chandrasekhar9781c6c2014-12-01 05:49:35 -08003307 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003308 pthread_mutex_unlock(&adev->lock);
3309
3310 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311}
3312
3313static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3314{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003315 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316 return 0;
3317}
3318
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303319static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003320 const struct audio_config *config)
3321{
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303322 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003323
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003324 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3325 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326}
3327
3328static int adev_open_input_stream(struct audio_hw_device *dev,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303329 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003330 audio_devices_t devices,
3331 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303332 struct audio_stream_in **stream_in,
3333 audio_input_flags_t flags __unused,
3334 const char *address __unused,
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003335 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336{
3337 struct audio_device *adev = (struct audio_device *)dev;
3338 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003339 int ret = 0, buffer_size, frame_size;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303340 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003341 bool is_low_latency = false;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303342
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003343 *stream_in = NULL;
3344 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3345 return -EINVAL;
3346
3347 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003348
3349 if (!in) {
3350 ALOGE("failed to allocate input stream");
3351 return -ENOMEM;
3352 }
3353
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303354 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003355 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3356 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003357
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003358 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurent35455462015-06-19 16:30:44 -07003359 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003360
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003361 in->stream.common.get_sample_rate = in_get_sample_rate;
3362 in->stream.common.set_sample_rate = in_set_sample_rate;
3363 in->stream.common.get_buffer_size = in_get_buffer_size;
3364 in->stream.common.get_channels = in_get_channels;
3365 in->stream.common.get_format = in_get_format;
3366 in->stream.common.set_format = in_set_format;
3367 in->stream.common.standby = in_standby;
3368 in->stream.common.dump = in_dump;
3369 in->stream.common.set_parameters = in_set_parameters;
3370 in->stream.common.get_parameters = in_get_parameters;
3371 in->stream.common.add_audio_effect = in_add_audio_effect;
3372 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3373 in->stream.set_gain = in_set_gain;
3374 in->stream.read = in_read;
3375 in->stream.get_input_frames_lost = in_get_input_frames_lost;
3376
3377 in->device = devices;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003378 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380 in->standby = 1;
3381 in->channel_mask = config->channel_mask;
3382
3383 /* Update config params with the requested sample rate and channels */
3384 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003385 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3386 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3387 is_low_latency = true;
3388#if LOW_LATENCY_CAPTURE_USE_CASE
3389 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3390#endif
3391 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003394 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003395
Scott Mertz8e017862016-03-16 09:31:48 -07003396 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkala3c0036d2014-12-17 16:45:10 +05303397 if (adev->mode != AUDIO_MODE_IN_CALL) {
3398 ret = -EINVAL;
3399 goto err_open;
Pavan Chikkala3ec42ef2014-11-21 20:57:48 +05303400 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303401 if (config->sample_rate == 0)
3402 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3403 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3404 config->sample_rate != 8000) {
3405 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3406 ret = -EINVAL;
3407 goto err_open;
3408 }
3409 if (config->format == AUDIO_FORMAT_DEFAULT)
3410 config->format = AUDIO_FORMAT_PCM_16_BIT;
3411 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3412 config->format = AUDIO_FORMAT_PCM_16_BIT;
3413 ret = -EINVAL;
3414 goto err_open;
3415 }
3416 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3417 in->config = pcm_config_afe_proxy_record;
3418 in->config.channels = channel_count;
3419 in->config.rate = config->sample_rate;
3420 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003421 if(audio_extn_ssr_get_enabled()) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303422 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003423 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3424 ret = -EINVAL;
3425 goto err_open;
3426 }
3427 } else {
Mingming Yindaf9c542014-09-16 17:41:33 -07003428 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003429 }
Mingming Yine62d7842013-10-25 16:26:03 -07003430 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08003431 audio_extn_compr_cap_format_supported(config->format) &&
3432 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303433 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003434 } else {
3435 in->config.channels = channel_count;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303436 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003437 buffer_size = get_input_buffer_size(config->sample_rate,
3438 config->format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003439 channel_count,
3440 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003441 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003442 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3443 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3444 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3445 (in->config.rate == 8000 || in->config.rate == 16000) &&
3446 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3447 voice_extn_compress_voip_open_input_stream(in);
3448 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003449 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450
3451 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003452 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003453 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003454
3455err_open:
3456 free(in);
3457 *stream_in = NULL;
3458 return ret;
3459}
3460
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303461static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003462 struct audio_stream_in *stream)
3463{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003464 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003465 struct stream_in *in = (struct stream_in *)stream;
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303466 struct audio_device *adev = in->dev;
3467
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303468 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003469
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003470 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303471 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003472 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303473 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003474 if (ret != 0)
3475 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3476 __func__, ret);
3477 } else
3478 in_standby(&stream->common);
3479
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303480 if (audio_extn_ssr_get_enabled() &&
3481 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003482 audio_extn_ssr_deinit();
3483 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 free(stream);
3485
Mingming Yine62d7842013-10-25 16:26:03 -07003486 if(audio_extn_compr_cap_enabled() &&
3487 audio_extn_compr_cap_format_supported(in->config.format))
3488 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003489 return;
3490}
3491
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303492static int adev_dump(const audio_hw_device_t *device __unused,
3493 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003494{
3495 return 0;
3496}
3497
Steve Kondik3abbbc82014-11-29 14:14:43 -08003498/* verifies input and output devices and their capabilities.
3499 *
3500 * This verification is required when enabling extended bit-depth or
3501 * sampling rates, as not all qcom products support it.
3502 *
3503 * Suitable for calling only on initialization such as adev_open().
3504 * It fills the audio_device use_case_table[] array.
3505 *
3506 * Has a side-effect that it needs to configure audio routing / devices
3507 * in order to power up the devices and read the device parameters.
3508 * It does not acquire any hw device lock. Should restore the devices
3509 * back to "normal state" upon completion.
3510 */
3511static int adev_verify_devices(struct audio_device *adev)
3512{
3513 /* enumeration is a bit difficult because one really wants to pull
3514 * the use_case, device id, etc from the hidden pcm_device_table[].
3515 * In this case there are the following use cases and device ids.
3516 *
3517 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3518 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3519 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3520 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3521 * [USECASE_AUDIO_RECORD] = {0, 0},
3522 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3523 * [USECASE_VOICE_CALL] = {2, 2},
3524 *
3525 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3526 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3527 */
3528
3529 /* should be the usecases enabled in adev_open_input_stream() */
3530 static const int test_in_usecases[] = {
3531 USECASE_AUDIO_RECORD,
3532 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3533 };
3534 /* should be the usecases enabled in adev_open_output_stream()*/
3535 static const int test_out_usecases[] = {
3536 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3537 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3538 };
3539 static const usecase_type_t usecase_type_by_dir[] = {
3540 PCM_PLAYBACK,
3541 PCM_CAPTURE,
3542 };
3543 static const unsigned flags_by_dir[] = {
3544 PCM_OUT,
3545 PCM_IN,
3546 };
3547
3548 size_t i;
3549 unsigned dir;
3550 const unsigned card_id = adev->snd_card;
3551 char info[512]; /* for possible debug info */
3552
3553 for (dir = 0; dir < 2; ++dir) {
3554 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3555 const unsigned flags_dir = flags_by_dir[dir];
3556 const size_t testsize =
3557 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3558 const int *testcases =
3559 dir ? test_in_usecases : test_out_usecases;
3560 const audio_devices_t audio_device =
3561 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3562
3563 for (i = 0; i < testsize; ++i) {
3564 const audio_usecase_t audio_usecase = testcases[i];
3565 int device_id;
3566 snd_device_t snd_device;
3567 struct pcm_params **pparams;
3568 struct stream_out out;
3569 struct stream_in in;
3570 struct audio_usecase uc_info;
3571 int retval;
3572
3573 pparams = &adev->use_case_table[audio_usecase];
3574 pcm_params_free(*pparams); /* can accept null input */
3575 *pparams = NULL;
3576
3577 /* find the device ID for the use case (signed, for error) */
3578 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3579 if (device_id < 0)
3580 continue;
3581
3582 /* prepare structures for device probing */
3583 memset(&uc_info, 0, sizeof(uc_info));
3584 uc_info.id = audio_usecase;
3585 uc_info.type = usecase_type;
3586 if (dir) {
3587 adev->active_input = &in;
3588 memset(&in, 0, sizeof(in));
3589 in.device = audio_device;
3590 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3591 uc_info.stream.in = &in;
3592 } else {
3593 adev->active_input = NULL;
3594 }
3595 memset(&out, 0, sizeof(out));
3596 out.devices = audio_device; /* only field needed in select_devices */
3597 uc_info.stream.out = &out;
3598 uc_info.devices = audio_device;
3599 uc_info.in_snd_device = SND_DEVICE_NONE;
3600 uc_info.out_snd_device = SND_DEVICE_NONE;
3601 list_add_tail(&adev->usecase_list, &uc_info.list);
3602
3603 /* select device - similar to start_(in/out)put_stream() */
3604 retval = select_devices(adev, audio_usecase);
3605 if (retval >= 0) {
3606 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3607#if LOG_NDEBUG == 0
3608 if (*pparams) {
3609 ALOGV("%s: (%s) card %d device %d", __func__,
3610 dir ? "input" : "output", card_id, device_id);
3611 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Steve Kondik13582572015-12-05 17:19:19 -08003612 ALOGV("parms: %s", info); /* print parameters */
Steve Kondik3abbbc82014-11-29 14:14:43 -08003613 } else {
3614 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3615 }
3616#endif
3617 }
3618
3619 /* deselect device - similar to stop_(in/out)put_stream() */
3620 /* 1. Get and set stream specific mixer controls */
3621 retval = disable_audio_route(adev, &uc_info);
3622 /* 2. Disable the rx device */
3623 retval = disable_snd_device(adev,
3624 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
3625 list_remove(&uc_info.list);
3626 }
3627 }
3628 adev->active_input = NULL; /* restore adev state */
3629 return 0;
3630}
3631
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003632static int adev_close(hw_device_t *device)
3633{
Steve Kondik3abbbc82014-11-29 14:14:43 -08003634 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003635 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003636
3637 if (!adev)
3638 return 0;
3639
3640 pthread_mutex_lock(&adev_init_lock);
3641
3642 if ((--audio_device_ref_count) == 0) {
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303643 if (amplifier_close() != 0)
3644 ALOGE("Amplifier close failed");
Kiran Kandide144c82013-11-20 15:58:32 -08003645 audio_extn_listen_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07003646 audio_route_free(adev->audio_route);
3647 free(adev->snd_dev_ref_cnt);
3648 platform_deinit(adev->platform);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003649 audio_extn_extspk_deinit(adev->extspk);
Steve Kondik3abbbc82014-11-29 14:14:43 -08003650 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3651 pcm_params_free(adev->use_case_table[i]);
3652 }
Kiran Kandi910e1862013-10-29 13:29:42 -07003653 free(device);
3654 adev = NULL;
3655 }
3656 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003657 return 0;
3658}
3659
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003660/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3661 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3662 * just that it _might_ work.
3663 */
3664static int period_size_is_plausible_for_low_latency(int period_size)
3665{
3666 switch (period_size) {
Glenn Kasten44b01922015-04-09 09:43:29 -07003667 case 48:
3668 case 96:
3669 case 144:
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003670 case 160:
Glenn Kasten44b01922015-04-09 09:43:29 -07003671 case 192:
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003672 case 240:
3673 case 320:
3674 case 480:
3675 return 1;
3676 default:
3677 return 0;
3678 }
3679}
3680
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681static int adev_open(const hw_module_t *module, const char *name,
3682 hw_device_t **device)
3683{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003684 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003685
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003686 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3688
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003689 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003690 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003691 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003692 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003693 ALOGD("%s: returning existing instance of adev", __func__);
3694 ALOGD("%s: exit", __func__);
3695 pthread_mutex_unlock(&adev_init_lock);
3696 return 0;
3697 }
3698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003699 adev = calloc(1, sizeof(struct audio_device));
3700
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003701 if (!adev) {
3702 pthread_mutex_unlock(&adev_init_lock);
3703 return -ENOMEM;
3704 }
3705
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003706 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3707
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3709 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3710 adev->device.common.module = (struct hw_module_t *)module;
3711 adev->device.common.close = adev_close;
3712
3713 adev->device.init_check = adev_init_check;
3714 adev->device.set_voice_volume = adev_set_voice_volume;
3715 adev->device.set_master_volume = adev_set_master_volume;
3716 adev->device.get_master_volume = adev_get_master_volume;
3717 adev->device.set_master_mute = adev_set_master_mute;
3718 adev->device.get_master_mute = adev_get_master_mute;
3719 adev->device.set_mode = adev_set_mode;
3720 adev->device.set_mic_mute = adev_set_mic_mute;
3721 adev->device.get_mic_mute = adev_get_mic_mute;
3722 adev->device.set_parameters = adev_set_parameters;
3723 adev->device.get_parameters = adev_get_parameters;
3724 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3725 adev->device.open_output_stream = adev_open_output_stream;
3726 adev->device.close_output_stream = adev_close_output_stream;
3727 adev->device.open_input_stream = adev_open_input_stream;
3728 adev->device.close_input_stream = adev_close_input_stream;
3729 adev->device.dump = adev_dump;
3730
3731 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003732 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003733 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003734 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003735 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003736 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003737 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003738 /* adev->cur_hdmi_channels = 0; by calloc() */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08003739 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3740 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003741 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003742 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003743 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly9b7e96b2014-02-14 14:45:49 -08003744 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003745 adev->offload_usecases_state = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003746
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303747 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3748 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
3749
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003750 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003751 adev->platform = platform_init(adev);
3752 if (!adev->platform) {
3753 free(adev->snd_dev_ref_cnt);
3754 free(adev);
3755 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3756 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003757 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003758 return -EINVAL;
3759 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003760
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303761 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
Eric Laurentda46bfb2014-08-25 22:39:29 -05003762 adev->extspk = audio_extn_extspk_init(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303763
Eric Laurentc4aef752013-09-12 17:45:53 -07003764 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3765 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3766 if (adev->visualizer_lib == NULL) {
3767 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3768 } else {
3769 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3770 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003771 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003772 "visualizer_hal_start_output");
3773 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003774 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003775 "visualizer_hal_stop_output");
3776 }
3777 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003778 audio_extn_listen_init(adev, adev->snd_card);
Eric Laurentc4aef752013-09-12 17:45:53 -07003779
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003780 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3781 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3782 if (adev->offload_effects_lib == NULL) {
3783 ALOGE("%s: DLOPEN failed for %s", __func__,
3784 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3785 } else {
3786 ALOGV("%s: DLOPEN successful for %s", __func__,
3787 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3788 adev->offload_effects_start_output =
3789 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3790 "offload_effects_bundle_hal_start_output");
3791 adev->offload_effects_stop_output =
3792 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3793 "offload_effects_bundle_hal_stop_output");
3794 }
3795 }
3796
Dan Pasanend4c2ca92015-08-10 19:47:43 -05003797 if (amplifier_open() != 0)
3798 ALOGE("Amplifier initialization failed");
3799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003800 *device = &adev->device.common;
Steve Kondik3abbbc82014-11-29 14:14:43 -08003801 if (k_enable_extended_precision)
3802 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003803
Kiran Kandi910e1862013-10-29 13:29:42 -07003804 audio_device_ref_count++;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003805
3806 char value[PROPERTY_VALUE_MAX];
3807 int trial;
3808 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3809 trial = atoi(value);
3810 if (period_size_is_plausible_for_low_latency(trial)) {
3811 pcm_config_low_latency.period_size = trial;
3812 pcm_config_low_latency.start_threshold = trial / 4;
3813 pcm_config_low_latency.avail_min = trial / 4;
3814 configured_low_latency_capture_period_size = trial;
3815 }
3816 }
3817 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3818 trial = atoi(value);
3819 if (period_size_is_plausible_for_low_latency(trial)) {
3820 configured_low_latency_capture_period_size = trial;
3821 }
3822 }
3823
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003824 pthread_mutex_unlock(&adev_init_lock);
3825
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07003826 audio_extn_perf_lock_init();
3827
Eric Laurent994a6932013-07-17 11:51:42 -07003828 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003829 return 0;
3830}
3831
3832static struct hw_module_methods_t hal_module_methods = {
3833 .open = adev_open,
3834};
3835
3836struct audio_module HAL_MODULE_INFO_SYM = {
3837 .common = {
3838 .tag = HARDWARE_MODULE_TAG,
3839 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3840 .hal_api_version = HARDWARE_HAL_API_VERSION,
3841 .id = AUDIO_HARDWARE_MODULE_ID,
3842 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003843 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844 .methods = &hal_module_methods,
3845 },
3846};