blob: cfb1bd5acc6e190b491b28bdebac70243b77ddef [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 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700927 }
928 if (usecase->type == PCM_PLAYBACK) {
929 usecase->devices = usecase->stream.out->devices;
930 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700931 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700932 out_snd_device = platform_get_output_snd_device(adev->platform,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700933 usecase->stream.out->devices);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700934 if (usecase->stream.out == adev->primary_output &&
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530935 adev->active_input ) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700936 select_devices(adev, adev->active_input->usecase);
937 }
938 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700939 } else if (usecase->type == PCM_CAPTURE) {
940 usecase->devices = usecase->stream.in->device;
941 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700942 if (in_snd_device == SND_DEVICE_NONE) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530943 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Shreyas Nagasandra Chandrasekhar23b3af22014-09-03 19:10:01 +0530944 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 -0700945 adev->primary_output && !adev->primary_output->standby) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +0530946 out_device = adev->primary_output->devices;
947 } else if(usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
948 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700949 }
LiuShangfe0bc342015-02-17 18:20:11 +0800950
951 /*
952 * Select a specific device microphone if we are in test mode.
953 */
954 switch (mFpTestMicSource) {
955 case FP_TEST_PRIMARY_MIC:
956 ALOGD("FP test selected primary mic.");
957 in_snd_device = SND_DEVICE_IN_HANDSET_MIC;
958 break;
959 case FP_TEST_SECONDARY_MIC:
960 ALOGD("FP test selected secondary mic.");
961 in_snd_device = SND_DEVICE_IN_SPEAKER_MIC;
962 break;
963 case FP_TEST_DEFAULT_MIC:
964 default:
965 ALOGV("FP test disabled");
966 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
967 break;
968 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -0700969 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700970 }
971 }
972
973 if (out_snd_device == usecase->out_snd_device &&
974 in_snd_device == usecase->in_snd_device) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800975 return 0;
976 }
977
sangwoobc677242013-08-08 16:53:43 +0900978 ALOGD("%s: out_snd_device(%d: %s) in_snd_device(%d: %s)", __func__,
Eric Laurentb23d5282013-05-14 15:27:20 -0700979 out_snd_device, platform_get_snd_device_name(out_snd_device),
980 in_snd_device, platform_get_snd_device_name(in_snd_device));
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -0800981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800982 /*
983 * Limitation: While in call, to do a device switch we need to disable
984 * and enable both RX and TX devices though one of them is same as current
985 * device.
986 */
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800987 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -0700988 status = platform_switch_voice_call_device_pre(adev->platform);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -0800989 }
990
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700991 /* Disable current sound devices */
992 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700993 disable_audio_route(adev, usecase);
994 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800995 }
996
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -0700997 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -0700998 disable_audio_route(adev, usecase);
999 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001000 }
1001
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001002 /* Enable new sound devices */
1003 if (out_snd_device != SND_DEVICE_NONE) {
1004 if (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)
1005 check_usecases_codec_backend(adev, usecase, out_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001006 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001007 }
1008
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001009 if (in_snd_device != SND_DEVICE_NONE) {
1010 check_and_route_capture_usecases(adev, usecase, in_snd_device);
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001011 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001012 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001013
Avinash Vaish8005dc82014-07-24 15:36:33 +05301014 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07001015 status = platform_switch_voice_call_device_post(adev->platform,
1016 out_snd_device,
1017 in_snd_device);
Avinash Vaish8005dc82014-07-24 15:36:33 +05301018 enable_audio_route_for_voice_usecases(adev, usecase);
1019 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08001020
sangwoo170731f2013-06-08 15:36:36 +09001021 usecase->in_snd_device = in_snd_device;
1022 usecase->out_snd_device = out_snd_device;
1023
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001024 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09001025
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301026 /* Rely on amplifier_set_devices to distinguish between in/out devices */
Ethan Chen79c356c2015-06-07 12:26:14 -07001027 amplifier_set_input_devices(in_snd_device);
1028 amplifier_set_output_devices(out_snd_device);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05301029
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08001030 /* Applicable only on the targets that has external modem.
1031 * Enable device command should be sent to modem only after
1032 * enabling voice call mixer controls
1033 */
1034 if (usecase->type == VOICE_CALL)
1035 status = platform_switch_voice_call_usecase_route_post(adev->platform,
1036 out_snd_device,
1037 in_snd_device);
1038
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301039 ALOGD("%s: done",__func__);
1040
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001041 return status;
1042}
1043
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001044static int stop_input_stream(struct stream_in *in)
1045{
1046 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001047 struct audio_usecase *uc_info;
1048 struct audio_device *adev = in->dev;
1049
Eric Laurentc8400632013-02-14 19:04:54 -08001050 adev->active_input = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001051
Eric Laurent994a6932013-07-17 11:51:42 -07001052 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001053 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001054 uc_info = get_usecase_from_list(adev, in->usecase);
1055 if (uc_info == NULL) {
1056 ALOGE("%s: Could not find the usecase (%d) in the list",
1057 __func__, in->usecase);
1058 return -EINVAL;
1059 }
1060
Vidyakumar Athota2850d532013-11-19 16:02:12 -08001061 /* Close in-call recording streams */
1062 voice_check_and_stop_incall_rec_usecase(adev, in);
1063
Eric Laurent150dbfe2013-02-27 14:31:02 -08001064 /* 1. Disable stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001065 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001066
1067 /* 2. Disable the tx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001068 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001069
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001070 list_remove(&uc_info->list);
1071 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001072
Eric Laurent994a6932013-07-17 11:51:42 -07001073 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001074 return ret;
1075}
1076
1077int start_input_stream(struct stream_in *in)
1078{
1079 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08001080 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001081 struct audio_usecase *uc_info;
1082 struct audio_device *adev = in->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301083 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001084
Ramjee Singh240ac652015-07-31 16:12:29 +05301085 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
1086 if (get_usecase_from_list(adev, usecase) == NULL)
1087 in->usecase = usecase;
1088
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301089 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
1090 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001091
Naresh Tannirucef332d2014-06-04 18:17:56 +05301092 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
1093 ALOGE("%s: sound card is not active/SSR returning error ", __func__);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301094 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301095 goto error_config;
1096 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301097
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07001098 /* Check if source matches incall recording usecase criteria */
1099 ret = voice_check_and_set_incall_rec_usecase(adev, in);
1100 if (ret)
1101 goto error_config;
1102 else
1103 ALOGV("%s: usecase(%d)", __func__, in->usecase);
1104
Ramjee Singh240ac652015-07-31 16:12:29 +05301105 if (get_usecase_from_list(adev, in->usecase) != NULL) {
1106 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
1107 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
1108 goto error_config;
1109 }
1110
Eric Laurentb23d5282013-05-14 15:27:20 -07001111 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001112 if (in->pcm_device_id < 0) {
1113 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
1114 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08001115 ret = -EINVAL;
1116 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001117 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001118
1119 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001120 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001121
1122 if (!uc_info) {
1123 ret = -ENOMEM;
1124 goto error_config;
1125 }
1126
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001127 uc_info->id = in->usecase;
1128 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001129 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001130 uc_info->devices = in->device;
1131 uc_info->in_snd_device = SND_DEVICE_NONE;
1132 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001133
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001134 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001135
1136 audio_extn_perf_lock_acquire();
1137
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001138 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001139
Eric Laurentc8400632013-02-14 19:04:54 -08001140 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301141 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
1142
Andy Hung6cd0c612016-01-15 17:46:57 -08001143 unsigned int flags = PCM_IN | PCM_MONOTONIC;
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301144 unsigned int pcm_open_retry_entry_count = 0;
1145
1146 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
1147 flags |= PCM_MMAP | PCM_NOIRQ;
1148 pcm_open_retry_entry_count = PROXY_OPEN_RETRY_COUNT;
1149 }
1150
1151 while(1) {
1152 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
1153 flags, &in->config);
1154 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
1155 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
1156 if (in->pcm != NULL) {
1157 pcm_close(in->pcm);
1158 in->pcm = NULL;
1159 }
1160 if (pcm_open_retry_entry_count-- == 0) {
1161 ret = -EIO;
1162 goto error_open;
1163 }
1164 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1165 continue;
1166 }
1167 break;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001168 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301169
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001170 audio_extn_perf_lock_release();
1171
Eric Laurent994a6932013-07-17 11:51:42 -07001172 ALOGV("%s: exit", __func__);
Eric Laurentc8400632013-02-14 19:04:54 -08001173 return ret;
1174
1175error_open:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001176 stop_input_stream(in);
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001177 audio_extn_perf_lock_release();
Eric Laurentc8400632013-02-14 19:04:54 -08001178
1179error_config:
1180 adev->active_input = NULL;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 ALOGD("%s: exit: status(%d)", __func__, ret);
Eric Laurentc8400632013-02-14 19:04:54 -08001182
1183 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001184}
1185
Eric Laurent35455462015-06-19 16:30:44 -07001186void lock_input_stream(struct stream_in *in)
1187{
1188 pthread_mutex_lock(&in->pre_lock);
1189 pthread_mutex_lock(&in->lock);
1190 pthread_mutex_unlock(&in->pre_lock);
1191}
1192
1193void lock_output_stream(struct stream_out *out)
1194{
1195 pthread_mutex_lock(&out->pre_lock);
1196 pthread_mutex_lock(&out->lock);
1197 pthread_mutex_unlock(&out->pre_lock);
1198}
1199
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001200/* must be called with out->lock locked */
1201static int send_offload_cmd_l(struct stream_out* out, int command)
1202{
1203 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
1204
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001205 if (!cmd) {
1206 ALOGE("failed to allocate mem for command 0x%x", command);
1207 return -ENOMEM;
1208 }
1209
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001210 ALOGVV("%s %d", __func__, command);
1211
1212 cmd->cmd = command;
1213 list_add_tail(&out->offload_cmd_list, &cmd->node);
1214 pthread_cond_signal(&out->offload_cond);
1215 return 0;
1216}
1217
1218/* must be called iwth out->lock locked */
1219static void stop_compressed_output_l(struct stream_out *out)
1220{
1221 out->offload_state = OFFLOAD_STATE_IDLE;
1222 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001223 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001224 if (out->compr != NULL) {
1225 compress_stop(out->compr);
1226 while (out->offload_thread_blocked) {
1227 pthread_cond_wait(&out->cond, &out->lock);
1228 }
1229 }
1230}
1231
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001232bool is_offload_usecase(audio_usecase_t uc_id)
1233{
1234 unsigned int i;
1235 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1236 if (uc_id == offload_usecases[i])
1237 return true;
1238 }
1239 return false;
1240}
1241
1242static audio_usecase_t get_offload_usecase(struct audio_device *adev)
1243{
1244 audio_usecase_t ret = USECASE_AUDIO_PLAYBACK_OFFLOAD;
1245 unsigned int i, num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
1246 char value[PROPERTY_VALUE_MAX] = {0};
1247
1248 property_get("audio.offload.multiple.enabled", value, NULL);
1249 if (!(atoi(value) || !strncmp("true", value, 4)))
1250 num_usecase = 1; /* If prop is not set, limit the num of offload usecases to 1 */
1251
1252 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
1253 for (i = 0; i < num_usecase; i++) {
1254 if (!(adev->offload_usecases_state & (0x1<<i))) {
1255 adev->offload_usecases_state |= 0x1 << i;
1256 ret = offload_usecases[i];
1257 break;
1258 }
1259 }
1260 ALOGV("%s: offload usecase is %d", __func__, ret);
1261 return ret;
1262}
1263
1264static void free_offload_usecase(struct audio_device *adev,
1265 audio_usecase_t uc_id)
1266{
1267 unsigned int i;
1268 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
1269 if (offload_usecases[i] == uc_id) {
1270 adev->offload_usecases_state &= ~(0x1<<i);
1271 break;
1272 }
1273 }
1274 ALOGV("%s: free offload usecase %d", __func__, uc_id);
1275}
1276
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001277static void *offload_thread_loop(void *context)
1278{
1279 struct stream_out *out = (struct stream_out *) context;
1280 struct listnode *item;
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001281 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001282
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001283 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
1284 set_sched_policy(0, SP_FOREGROUND);
1285 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
1286
1287 ALOGV("%s", __func__);
Eric Laurent35455462015-06-19 16:30:44 -07001288 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001289 for (;;) {
1290 struct offload_cmd *cmd = NULL;
1291 stream_callback_event_t event;
1292 bool send_callback = false;
1293
1294 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
1295 __func__, list_empty(&out->offload_cmd_list),
1296 out->offload_state);
1297 if (list_empty(&out->offload_cmd_list)) {
1298 ALOGV("%s SLEEPING", __func__);
1299 pthread_cond_wait(&out->offload_cond, &out->lock);
1300 ALOGV("%s RUNNING", __func__);
1301 continue;
1302 }
1303
1304 item = list_head(&out->offload_cmd_list);
1305 cmd = node_to_item(item, struct offload_cmd, node);
1306 list_remove(item);
1307
1308 ALOGVV("%s STATE %d CMD %d out->compr %p",
1309 __func__, out->offload_state, cmd->cmd, out->compr);
1310
1311 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
1312 free(cmd);
1313 break;
1314 }
1315
1316 if (out->compr == NULL) {
1317 ALOGE("%s: Compress handle is NULL", __func__);
1318 pthread_cond_signal(&out->cond);
1319 continue;
1320 }
1321 out->offload_thread_blocked = true;
1322 pthread_mutex_unlock(&out->lock);
1323 send_callback = false;
1324 switch(cmd->cmd) {
1325 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Steve Kondik05c17962015-02-25 00:55:50 -08001326 ALOGV("copl(%x):calling compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001327 compress_wait(out->compr, -1);
Steve Kondik05c17962015-02-25 00:55:50 -08001328 ALOGV("copl(%x):out of compress_wait", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001329 send_callback = true;
1330 event = STREAM_CBK_EVENT_WRITE_READY;
1331 break;
1332 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001333 ret = compress_next_track(out->compr);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301334 if(ret == 0) {
Steve Kondik05c17962015-02-25 00:55:50 -08001335 ALOGV("copl(%p):calling compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301336 ret = compress_partial_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001337 ALOGV("copl(%p):out of compress_partial_drain", out);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301338 if (ret < 0)
1339 ret = -errno;
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301340 }
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301341 else if (ret == -ETIMEDOUT)
Krishnankutty Kolathappilly0fe78f02014-01-06 18:33:58 -08001342 compress_drain(out->compr);
1343 else
1344 ALOGE("%s: Next track returned error %d",__func__, ret);
Dhanalakshmi Siddani5754e2c2014-12-23 16:57:43 +05301345
Alexy Joseph505da3f2015-09-10 01:31:51 -07001346 send_callback = true;
1347 event = STREAM_CBK_EVENT_DRAIN_READY;
1348 pthread_mutex_lock(&out->lock);
1349 /* Resend the metadata for next iteration */
1350 out->send_new_metadata = 1;
1351 out->send_next_track_params = true;
1352 pthread_mutex_unlock(&out->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001353 break;
1354 case OFFLOAD_CMD_DRAIN:
Steve Kondik05c17962015-02-25 00:55:50 -08001355 ALOGV("copl(%x):calling compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001356 compress_drain(out->compr);
Steve Kondik05c17962015-02-25 00:55:50 -08001357 ALOGV("copl(%x):out of compress_drain", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001358 send_callback = true;
1359 event = STREAM_CBK_EVENT_DRAIN_READY;
1360 break;
1361 default:
1362 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
1363 break;
1364 }
Eric Laurent35455462015-06-19 16:30:44 -07001365 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001366 out->offload_thread_blocked = false;
1367 pthread_cond_signal(&out->cond);
Eric Laurent6e895242013-09-05 16:10:57 -07001368 if (send_callback) {
Ravi Kumar Alamanda3d316172014-12-02 19:21:51 -08001369 ALOGVV("%s: sending offload_callback event %d", __func__, event);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001370 out->offload_callback(event, NULL, out->offload_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07001371 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001372 free(cmd);
1373 }
1374
1375 pthread_cond_signal(&out->cond);
1376 while (!list_empty(&out->offload_cmd_list)) {
1377 item = list_head(&out->offload_cmd_list);
1378 list_remove(item);
1379 free(node_to_item(item, struct offload_cmd, node));
1380 }
1381 pthread_mutex_unlock(&out->lock);
1382
1383 return NULL;
1384}
1385
1386static int create_offload_callback_thread(struct stream_out *out)
1387{
1388 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
1389 list_init(&out->offload_cmd_list);
1390 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
1391 offload_thread_loop, out);
1392 return 0;
1393}
1394
1395static int destroy_offload_callback_thread(struct stream_out *out)
1396{
Eric Laurent35455462015-06-19 16:30:44 -07001397 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001398 stop_compressed_output_l(out);
1399 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
1400
1401 pthread_mutex_unlock(&out->lock);
1402 pthread_join(out->offload_thread, (void **) NULL);
1403 pthread_cond_destroy(&out->offload_cond);
1404
1405 return 0;
1406}
1407
Eric Laurent07eeafd2013-10-06 12:52:49 -07001408static bool allow_hdmi_channel_config(struct audio_device *adev)
1409{
1410 struct listnode *node;
1411 struct audio_usecase *usecase;
1412 bool ret = true;
1413
1414 list_for_each(node, &adev->usecase_list) {
1415 usecase = node_to_item(node, struct audio_usecase, list);
1416 if (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
1417 /*
1418 * If voice call is already existing, do not proceed further to avoid
1419 * disabling/enabling both RX and TX devices, CSD calls, etc.
1420 * Once the voice call done, the HDMI channels can be configured to
1421 * max channels of remaining use cases.
1422 */
1423 if (usecase->id == USECASE_VOICE_CALL) {
1424 ALOGD("%s: voice call is active, no change in HDMI channels",
1425 __func__);
1426 ret = false;
1427 break;
1428 } else if (usecase->id == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
1429 ALOGD("%s: multi channel playback is active, "
1430 "no change in HDMI channels", __func__);
1431 ret = false;
1432 break;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001433 } else if (is_offload_usecase(usecase->id) &&
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301434 audio_channel_count_from_out_mask(usecase->stream.out->channel_mask) > 2) {
Mingming Yin3ed162b2014-02-24 17:56:01 -08001435 ALOGD("%s: multi-channel(%x) compress offload playback is active, "
1436 "no change in HDMI channels", __func__, usecase->stream.out->channel_mask);
1437 ret = false;
1438 break;
Eric Laurent07eeafd2013-10-06 12:52:49 -07001439 }
1440 }
1441 }
1442 return ret;
1443}
1444
1445static int check_and_set_hdmi_channels(struct audio_device *adev,
1446 unsigned int channels)
1447{
1448 struct listnode *node;
1449 struct audio_usecase *usecase;
1450
1451 /* Check if change in HDMI channel config is allowed */
1452 if (!allow_hdmi_channel_config(adev))
1453 return 0;
1454
1455 if (channels == adev->cur_hdmi_channels) {
Mingming Yin10fef6a2013-11-26 17:17:01 -08001456 ALOGD("%s: Requested channels are same as current channels(%d)", __func__, channels);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001457 return 0;
1458 }
1459
1460 platform_set_hdmi_channels(adev->platform, channels);
1461 adev->cur_hdmi_channels = channels;
1462
1463 /*
1464 * Deroute all the playback streams routed to HDMI so that
1465 * the back end is deactivated. Note that backend will not
1466 * be deactivated if any one stream is connected to it.
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 disable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001473 }
1474 }
1475
1476 /*
1477 * Enable all the streams disabled above. Now the HDMI backend
1478 * will be activated with new channel configuration
1479 */
1480 list_for_each(node, &adev->usecase_list) {
1481 usecase = node_to_item(node, struct audio_usecase, list);
1482 if (usecase->type == PCM_PLAYBACK &&
1483 usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001484 enable_audio_route(adev, usecase);
Eric Laurent07eeafd2013-10-06 12:52:49 -07001485 }
1486 }
1487
1488 return 0;
1489}
1490
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001491static int stop_output_stream(struct stream_out *out)
1492{
1493 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001494 struct audio_usecase *uc_info;
1495 struct audio_device *adev = out->dev;
1496
Eric Laurent994a6932013-07-17 11:51:42 -07001497 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001498 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001499 uc_info = get_usecase_from_list(adev, out->usecase);
1500 if (uc_info == NULL) {
1501 ALOGE("%s: Could not find the usecase (%d) in the list",
1502 __func__, out->usecase);
1503 return -EINVAL;
1504 }
1505
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001506 if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001507 if (adev->visualizer_stop_output != NULL)
1508 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
1509 if (adev->offload_effects_stop_output != NULL)
1510 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
1511 }
Eric Laurentc4aef752013-09-12 17:45:53 -07001512
Eric Laurent150dbfe2013-02-27 14:31:02 -08001513 /* 1. Get and set stream specific mixer controls */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001514 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001515
1516 /* 2. Disable the rx device */
Haynes Mathew Georgeea098922014-04-24 17:53:50 -07001517 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001518
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001519 list_remove(&uc_info->list);
1520 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001521
Eric Laurentda46bfb2014-08-25 22:39:29 -05001522 audio_extn_extspk_update(adev->extspk);
1523
Eric Laurent07eeafd2013-10-06 12:52:49 -07001524 /* Must be called after removing the usecase from list */
1525 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
1526 check_and_set_hdmi_channels(adev, DEFAULT_HDMI_OUT_CHANNELS);
1527
Eric Laurent994a6932013-07-17 11:51:42 -07001528 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001529 return ret;
1530}
1531
1532int start_output_stream(struct stream_out *out)
1533{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001534 int ret = 0;
Mingming Yin6c344432014-05-01 15:37:31 -07001535 int sink_channels = 0;
1536 char prop_value[PROPERTY_VALUE_MAX] = {0};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001537 struct audio_usecase *uc_info;
1538 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05301539 int snd_card_status = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001540
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001541 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
1542 ret = -EINVAL;
1543 goto error_config;
1544 }
1545
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301546 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x)",
1547 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
1548 out->devices);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301549
Naresh Tannirucef332d2014-06-04 18:17:56 +05301550 if (SND_CARD_STATE_OFFLINE == snd_card_status) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301551 ALOGE("%s: sound card is not active/SSR returning error", __func__);
1552 ret = -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301553 goto error_config;
1554 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05301555
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301556 ALOGD("%s: enter: usecase(%d: %s) devices(%#x)",
1557 __func__, out->usecase, use_case_table[out->usecase], out->devices);
Eric Laurentb23d5282013-05-14 15:27:20 -07001558 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001559 if (out->pcm_device_id < 0) {
1560 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
1561 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001562 ret = -EINVAL;
1563 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001564 }
1565
1566 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001567
1568 if (!uc_info) {
1569 ret = -ENOMEM;
1570 goto error_config;
1571 }
1572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001573 uc_info->id = out->usecase;
1574 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001575 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001576 uc_info->devices = out->devices;
1577 uc_info->in_snd_device = SND_DEVICE_NONE;
1578 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001579
Eric Laurent07eeafd2013-10-06 12:52:49 -07001580 /* This must be called before adding this usecase to the list */
Mingming Yin10fef6a2013-11-26 17:17:01 -08001581 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Mingming Yin6c344432014-05-01 15:37:31 -07001582 property_get("audio.use.hdmi.sink.cap", prop_value, NULL);
1583 if (!strncmp("true", prop_value, 4)) {
1584 sink_channels = platform_edid_get_max_channels(out->dev->platform);
1585 ALOGD("%s: set HDMI channel count[%d] based on sink capability", __func__, sink_channels);
1586 check_and_set_hdmi_channels(adev, sink_channels);
1587 } else {
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001588 if (is_offload_usecase(out->usecase))
Mingming Yin6c344432014-05-01 15:37:31 -07001589 check_and_set_hdmi_channels(adev, out->compr_config.codec->ch_in);
1590 else
1591 check_and_set_hdmi_channels(adev, out->config.channels);
1592 }
Mingming Yin10fef6a2013-11-26 17:17:01 -08001593 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07001594
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001595 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001596
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001597 audio_extn_perf_lock_acquire();
1598
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001599 select_devices(adev, out->usecase);
1600
Eric Laurentda46bfb2014-08-25 22:39:29 -05001601 audio_extn_extspk_update(adev->extspk);
1602
Steve Kondik3abbbc82014-11-29 14:14:43 -08001603 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
1604 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
1605
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001606 if (!is_offload_usecase(out->usecase)) {
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301607 unsigned int flags = PCM_OUT;
1608 unsigned int pcm_open_retry_count = 0;
1609 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
1610 flags |= PCM_MMAP | PCM_NOIRQ;
1611 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
1612 } else
1613 flags |= PCM_MONOTONIC;
1614
1615 while (1) {
1616 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
1617 flags, &out->config);
1618 if (out->pcm && !pcm_is_ready(out->pcm)) {
1619 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
1620 if (out->pcm != NULL) {
1621 pcm_close(out->pcm);
1622 out->pcm = NULL;
1623 }
1624 if (pcm_open_retry_count-- == 0) {
1625 ret = -EIO;
1626 goto error_open;
1627 }
1628 usleep(PROXY_OPEN_WAIT_TIME * 1000);
1629 continue;
1630 }
1631 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001632 }
1633 } else {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001634 out->pcm = NULL;
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08001635 out->compr = compress_open(adev->snd_card,
1636 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001637 COMPRESS_IN, &out->compr_config);
1638 if (out->compr && !is_compress_ready(out->compr)) {
1639 ALOGE("%s: %s", __func__, compress_get_error(out->compr));
1640 compress_close(out->compr);
1641 out->compr = NULL;
1642 ret = -EIO;
1643 goto error_open;
1644 }
Alexy Joseph505da3f2015-09-10 01:31:51 -07001645 /* compress_open sends params of the track, so reset the flag here */
1646 out->is_compr_metadata_avail = false;
1647
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001648 if (out->offload_callback)
1649 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07001650
Fred Oh1483d8a2015-03-04 18:42:34 -08001651 /* Since small bufs uses blocking writes, a write will be blocked
1652 for the default max poll time (20s) in the event of an SSR.
1653 Reduce the poll time to observe and deal with SSR faster.
1654 */
1655 if (out->use_small_bufs) {
1656 compress_set_max_poll_wait(out->compr, 1000);
1657 }
1658
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08001659#ifdef DS1_DOLBY_DDP_ENABLED
1660 if (audio_extn_is_dolby_format(out->format))
1661 audio_extn_dolby_send_ddp_endp_params(adev);
1662#endif
1663
Eric Laurentc4aef752013-09-12 17:45:53 -07001664 if (adev->visualizer_start_output != NULL)
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08001665 adev->visualizer_start_output(out->handle, out->pcm_device_id);
1666 if (adev->offload_effects_start_output != NULL)
1667 adev->offload_effects_start_output(out->handle, out->pcm_device_id);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001668 }
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001669 audio_extn_perf_lock_release();
Eric Laurent994a6932013-07-17 11:51:42 -07001670 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001671 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001672error_open:
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07001673 audio_extn_perf_lock_release();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001674 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001675error_config:
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001676 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001677}
1678
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001679static int check_input_parameters(uint32_t sample_rate,
1680 audio_format_t format,
1681 int channel_count)
1682{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001683 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001684
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001685 if ((format != AUDIO_FORMAT_PCM_16_BIT) &&
Mingming Yine62d7842013-10-25 16:26:03 -07001686 !voice_extn_compress_voip_is_format_supported(format) &&
1687 !audio_extn_compr_cap_format_supported(format)) ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001688
1689 switch (channel_count) {
1690 case 1:
1691 case 2:
1692 case 6:
1693 break;
1694 default:
1695 ret = -EINVAL;
1696 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001697
1698 switch (sample_rate) {
1699 case 8000:
1700 case 11025:
1701 case 12000:
1702 case 16000:
1703 case 22050:
1704 case 24000:
1705 case 32000:
1706 case 44100:
1707 case 48000:
1708 break;
1709 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001710 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001711 }
1712
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08001713 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001714}
1715
1716static size_t get_input_buffer_size(uint32_t sample_rate,
1717 audio_format_t format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001718 int channel_count,
1719 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001720{
1721 size_t size = 0;
1722
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001723 if (check_input_parameters(sample_rate, format, channel_count) != 0)
1724 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001725
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001726 size = (sample_rate * AUDIO_CAPTURE_PERIOD_DURATION_MSEC) / 1000;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001727 if (is_low_latency)
1728 size = configured_low_latency_capture_period_size;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001729 /* ToDo: should use frame_size computed based on the format and
1730 channel_count here. */
1731 size *= sizeof(short) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07001733 /* make sure the size is multiple of 32 bytes
1734 * At 48 kHz mono 16-bit PCM:
1735 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
1736 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
1737 */
1738 size += 0x1f;
1739 size &= ~0x1f;
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07001740
1741 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001742}
1743
1744static uint32_t out_get_sample_rate(const struct audio_stream *stream)
1745{
1746 struct stream_out *out = (struct stream_out *)stream;
1747
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001748 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749}
1750
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301751static int out_set_sample_rate(struct audio_stream *stream __unused,
1752 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001753{
1754 return -ENOSYS;
1755}
1756
1757static size_t out_get_buffer_size(const struct audio_stream *stream)
1758{
1759 struct stream_out *out = (struct stream_out *)stream;
1760
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001761 if (is_offload_usecase(out->usecase))
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001762 return out->compr_config.fragment_size;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001763 else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
1764 return voice_extn_compress_voip_out_get_buffer_size(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001765
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05301766 return out->config.period_size *
1767 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768}
1769
1770static uint32_t out_get_channels(const struct audio_stream *stream)
1771{
1772 struct stream_out *out = (struct stream_out *)stream;
1773
1774 return out->channel_mask;
1775}
1776
1777static audio_format_t out_get_format(const struct audio_stream *stream)
1778{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001779 struct stream_out *out = (struct stream_out *)stream;
1780
1781 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782}
1783
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301784static int out_set_format(struct audio_stream *stream __unused,
1785 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001786{
1787 return -ENOSYS;
1788}
1789
1790static int out_standby(struct audio_stream *stream)
1791{
1792 struct stream_out *out = (struct stream_out *)stream;
1793 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001794
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301795 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
1796 stream, out->usecase, use_case_table[out->usecase]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001797 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
1798 /* Ignore standby in case of voip call because the voip output
1799 * stream is closed in adev_close_output_stream()
1800 */
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05301801 ALOGD("%s: Ignore Standby in VOIP call", __func__);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08001802 return 0;
1803 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001804
Eric Laurent35455462015-06-19 16:30:44 -07001805 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001806 if (!out->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08001807 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07001808
1809 amplifier_output_stream_standby((struct audio_stream_out *) stream);
1810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811 out->standby = true;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001812 if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001813 if (out->pcm) {
1814 pcm_close(out->pcm);
1815 out->pcm = NULL;
1816 }
1817 } else {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05301818 ALOGD("copl(%x):standby", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001819 stop_compressed_output_l(out);
Alexy Joseph505da3f2015-09-10 01:31:51 -07001820 out->send_next_track_params = false;
1821 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001822 out->gapless_mdata.encoder_delay = 0;
1823 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07001824 if (out->compr != NULL) {
1825 compress_close(out->compr);
1826 out->compr = NULL;
1827 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08001828 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001829 stop_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001830 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831 }
1832 pthread_mutex_unlock(&out->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07001833 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001834 return 0;
1835}
1836
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05301837static int out_dump(const struct audio_stream *stream __unused,
1838 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839{
1840 return 0;
1841}
1842
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001843static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
1844{
1845 int ret = 0;
1846 char value[32];
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001847
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001848 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001849 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001850 return -EINVAL;
1851 }
1852
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001853 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_FORMAT, value, sizeof(value));
1854 if (ret >= 0) {
1855 if (atoi(value) == SND_AUDIOSTREAMFORMAT_MP4ADTS) {
1856 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
1857 ALOGV("ADTS format is set in offload mode");
1858 }
ApurupaPattapudaa708c2013-12-18 15:47:59 -08001859 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001860 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
1861 if (ret >= 0) {
Alexy Joseph505da3f2015-09-10 01:31:51 -07001862 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001863 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001864 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
1865 if (ret >= 0) {
Alexy Joseph505da3f2015-09-10 01:31:51 -07001866 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001867 }
1868
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001869 ALOGV("%s new encoder delay %u and padding %u", __func__,
1870 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
1871
1872 return 0;
1873}
1874
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301875static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
1876{
1877 return out == adev->primary_output || out == adev->voice_tx_output;
1878}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001880static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
1881{
1882 struct stream_out *out = (struct stream_out *)stream;
1883 struct audio_device *adev = out->dev;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001884 struct audio_usecase *usecase;
1885 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001886 struct str_parms *parms;
1887 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001888 int ret = 0, val = 0, err;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001889 bool select_new_device = false;
Steve Kondik3abbbc82014-11-29 14:14:43 -08001890 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001891
sangwoobc677242013-08-08 16:53:43 +09001892 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001893 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001894 parms = str_parms_create_str(kvpairs);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08001895 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
1896 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001897 val = atoi(value);
Eric Laurent35455462015-06-19 16:30:44 -07001898 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001899 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001900
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001901 /*
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301902 * When HDMI cable is unplugged/usb hs is disconnected the
1903 * music playback is paused and the policy manager sends routing=0
1904 * But the audioflingercontinues to write data until standby time
1905 * (3sec). As the HDMI core is turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001906 * Avoid this by routing audio to speaker until standby.
1907 */
Dhanalakshmi Siddani523ae412014-04-18 22:26:56 +05301908 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL ||
Steve Kondikeadb6c82014-09-03 18:40:06 -07001909 out->devices == AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET ||
1910 out->devices == AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET) &&
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001911 val == AUDIO_DEVICE_NONE) {
1912 val = AUDIO_DEVICE_OUT_SPEAKER;
1913 }
1914
1915 /*
1916 * select_devices() call below switches all the usecases on the same
1917 * backend to the new device. Refer to check_usecases_codec_backend() in
1918 * the select_devices(). But how do we undo this?
1919 *
1920 * For example, music playback is active on headset (deep-buffer usecase)
1921 * and if we go to ringtones and select a ringtone, low-latency usecase
1922 * will be started on headset+speaker. As we can't enable headset+speaker
1923 * and headset devices at the same time, select_devices() switches the music
1924 * playback to headset+speaker while starting low-lateny usecase for ringtone.
1925 * So when the ringtone playback is completed, how do we undo the same?
1926 *
1927 * We are relying on the out_set_parameters() call on deep-buffer output,
1928 * once the ringtone playback is ended.
1929 * NOTE: We should not check if the current devices are same as new devices.
1930 * Because select_devices() must be called to switch back the music
1931 * playback to headset.
1932 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001933 if (val != 0) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001934 out->devices = val;
1935
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001936 if ((adev->mode == AUDIO_MODE_IN_CALL) &&
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301937 output_drives_call(adev, out)) {
1938 adev->current_call_output = out;
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001939 if (!adev->voice.in_call)
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05301940 ret = voice_start_call(adev);
1941 else
1942 voice_update_devices_for_all_voice_usecases(adev);
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001943 }
Shiv Maliyappanahalli889c0b32015-11-04 18:10:20 -08001944
1945 if (!out->standby)
1946 select_devices(adev, out->usecase);
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001947 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001948
Vidyakumar Athotaf85f6a22014-08-05 18:20:42 -07001949 if ((adev->mode == AUDIO_MODE_NORMAL) &&
1950 adev->voice.in_call &&
1951 output_drives_call(adev, out)) {
1952 ret = voice_stop_call(adev);
1953 adev->current_call_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001954 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001955
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08001957 pthread_mutex_unlock(&out->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05001958
1959 /*handles device and call state changes*/
1960 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001961 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001962
1963 if (out == adev->primary_output) {
1964 pthread_mutex_lock(&adev->lock);
1965 audio_extn_set_parameters(adev, parms);
1966 pthread_mutex_unlock(&adev->lock);
1967 }
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07001968 if (is_offload_usecase(out->usecase)) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001969 pthread_mutex_lock(&out->lock);
Steve Kondikba3b35d2014-07-18 01:49:48 -07001970 ret = parse_compress_metadata(out, parms);
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08001971 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07001972 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001973
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001974 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08001975 ALOGV("%s: exit: code(%d)", __func__, status);
1976 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001977}
1978
1979static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
1980{
1981 struct stream_out *out = (struct stream_out *)stream;
1982 struct str_parms *query = str_parms_create_str(keys);
1983 char *str;
1984 char value[256];
1985 struct str_parms *reply = str_parms_create();
1986 size_t i, j;
1987 int ret;
1988 bool first = true;
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07001989
1990 if (!query || !reply) {
1991 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
1992 return NULL;
1993 }
1994
Eric Laurent994a6932013-07-17 11:51:42 -07001995 ALOGV("%s: enter: keys - %s", __func__, keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001996 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
1997 if (ret >= 0) {
1998 value[0] = '\0';
1999 i = 0;
2000 while (out->supported_channel_masks[i] != 0) {
2001 for (j = 0; j < ARRAY_SIZE(out_channels_name_to_enum_table); j++) {
2002 if (out_channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
2003 if (!first) {
2004 strcat(value, "|");
2005 }
2006 strcat(value, out_channels_name_to_enum_table[j].name);
2007 first = false;
2008 break;
2009 }
2010 }
2011 i++;
2012 }
2013 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
2014 str = str_parms_to_str(reply);
2015 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002016 voice_extn_out_get_parameters(out, query, reply);
2017 str = str_parms_to_str(reply);
2018 if (!strncmp(str, "", sizeof(""))) {
Narsinga Rao Chella2e032352014-01-29 12:52:19 -08002019 free(str);
2020 str = strdup(keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002021 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002022 }
2023 str_parms_destroy(query);
2024 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07002025 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002026 return str;
2027}
2028
2029static uint32_t out_get_latency(const struct audio_stream_out *stream)
2030{
2031 struct stream_out *out = (struct stream_out *)stream;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002032 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002033
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002034 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002035 latency = COMPRESS_OFFLOAD_PLAYBACK_LATENCY;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002036 } else {
2037 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002038 (out->config.rate);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002039 }
2040
Anish Kumar1a0594f2014-12-09 04:01:39 +05302041 ALOGV("%s: Latency %d", __func__, latency);
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002042 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002043}
2044
2045static int out_set_volume(struct audio_stream_out *stream, float left,
2046 float right)
2047{
Eric Laurenta9024de2013-04-04 09:19:12 -07002048 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002049 int volume[2];
2050
Eric Laurenta9024de2013-04-04 09:19:12 -07002051 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
2052 /* only take left channel into account: the API is for stereo anyway */
2053 out->muted = (left == 0.0f);
2054 return 0;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002055 } else if (is_offload_usecase(out->usecase)) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002056 char mixer_ctl_name[128];
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002057 struct audio_device *adev = out->dev;
2058 struct mixer_ctl *ctl;
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002059 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
2060 PCM_PLAYBACK);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002061
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08002062 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
2063 "Compress Playback %d Volume", pcm_device_id);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002064 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2065 if (!ctl) {
2066 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2067 __func__, mixer_ctl_name);
2068 return -EINVAL;
2069 }
2070 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
2071 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
2072 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
2073 return 0;
Eric Laurenta9024de2013-04-04 09:19:12 -07002074 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002075
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002076 return -ENOSYS;
2077}
2078
2079static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
2080 size_t bytes)
2081{
2082 struct stream_out *out = (struct stream_out *)stream;
2083 struct audio_device *adev = out->dev;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302084 int snd_scard_state = get_snd_card_state(adev);
Eric Laurent6e895242013-09-05 16:10:57 -07002085 ssize_t ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002086
Eric Laurent35455462015-06-19 16:30:44 -07002087 lock_output_stream(out);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302088
Naresh Tannirucef332d2014-06-04 18:17:56 +05302089 if (SND_CARD_STATE_OFFLINE == snd_scard_state) {
2090 if (out->pcm) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302091 ALOGD(" %s: sound card is not active/SSR state", __func__);
2092 ret= -ENETRESET;
2093 goto exit;
Alexy Joseph55204352014-10-06 12:15:01 -07002094 } else if (is_offload_usecase(out->usecase)) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302095 //during SSR for compress usecase we should return error to flinger
2096 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
2097 pthread_mutex_unlock(&out->lock);
2098 return -ENETRESET;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302099 }
2100 }
2101
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002102 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002103 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002104 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002105 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
2106 ret = voice_extn_compress_voip_start_output_stream(out);
2107 else
2108 ret = start_output_stream(out);
Ethan Chen79c356c2015-06-07 12:26:14 -07002109
2110 if (ret == 0)
2111 amplifier_output_stream_start(stream,
2112 is_offload_usecase(out->usecase));
2113
Eric Laurent150dbfe2013-02-27 14:31:02 -08002114 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002115 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002116 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002117 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002118 goto exit;
2119 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002121
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002122 if (is_offload_usecase(out->usecase)) {
Alexy Joseph62babb92015-03-03 19:01:03 -08002123 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002124 if (out->send_new_metadata) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302125 ALOGD("copl(%x):send new gapless metadata", (unsigned int)out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002126 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
2127 out->send_new_metadata = 0;
Alexy Joseph505da3f2015-09-10 01:31:51 -07002128 if (out->send_next_track_params && out->is_compr_metadata_avail) {
2129 ALOGD("copl(%p):send next track params in gapless", out);
2130 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
2131 out->send_next_track_params = false;
2132 out->is_compr_metadata_avail = false;
2133 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002134 }
2135
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002136 ret = compress_write(out->compr, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302137 if (ret < 0)
2138 ret = -errno;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002139 ALOGVV("%s: writing buffer (%d bytes) to compress device returned %d", __func__, bytes, ret);
Eric Laurent6e895242013-09-05 16:10:57 -07002140 if (ret >= 0 && ret < (ssize_t)bytes) {
Steve Kondik32c2e312016-02-14 11:40:38 -08002141 ALOGV("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002142 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302143 } else if (-ENETRESET == ret) {
2144 ALOGE("copl %s: received sound card offline state on compress write", __func__);
2145 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2146 pthread_mutex_unlock(&out->lock);
2147 out_standby(&out->stream.common);
2148 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002149 }
Naresh Tannirucef332d2014-06-04 18:17:56 +05302150 if (!out->playback_started && ret >= 0) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002151 compress_start(out->compr);
2152 out->playback_started = 1;
2153 out->offload_state = OFFLOAD_STATE_PLAYING;
2154 }
2155 pthread_mutex_unlock(&out->lock);
2156 return ret;
2157 } else {
2158 if (out->pcm) {
2159 if (out->muted)
2160 memset((void *)buffer, 0, bytes);
2161 ALOGVV("%s: writing buffer (%d bytes) to pcm device", __func__, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302162 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY)
2163 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes);
2164 else
2165 ret = pcm_write(out->pcm, (void *)buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302166 if (ret < 0)
2167 ret = -errno;
2168 else if (ret == 0)
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002169 out->written += bytes / (out->config.channels * sizeof(short));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002170 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002171 }
2172
2173exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302174 /* ToDo: There may be a corner case when SSR happens back to back during
2175 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302176 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302177 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302178 }
2179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180 pthread_mutex_unlock(&out->lock);
2181
2182 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002183 if (out->pcm)
2184 ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302185 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302186 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302187 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302188 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302189 out->standby = true;
2190 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002191 out_standby(&out->stream.common);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002192 usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
2193 out_get_sample_rate(&out->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002194 }
2195 return bytes;
2196}
2197
2198static int out_get_render_position(const struct audio_stream_out *stream,
2199 uint32_t *dsp_frames)
2200{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002201 struct stream_out *out = (struct stream_out *)stream;
Amit Shekharfaefb322014-09-08 14:08:19 -07002202
2203 if (dsp_frames == NULL)
2204 return -EINVAL;
2205
2206 *dsp_frames = 0;
2207 if (is_offload_usecase(out->usecase)) {
2208 ssize_t ret = 0;
Eric Laurent35455462015-06-19 16:30:44 -07002209 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002210 if (out->compr != NULL) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302211 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002212 &out->sample_rate);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302213 if (ret < 0)
2214 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002215 ALOGVV("%s rendered frames %d sample_rate %d",
2216 __func__, *dsp_frames, out->sample_rate);
2217 }
2218 pthread_mutex_unlock(&out->lock);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302219 if (-ENETRESET == ret) {
2220 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
2221 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
2222 return -EINVAL;
2223 } else if(ret < 0) {
Steve Kondik81506242014-07-21 16:12:57 -07002224 ALOGE(" ERROR: Unable to get time stamp from compress driver ret=%d", ret);
Naresh Tannirucef332d2014-06-04 18:17:56 +05302225 return -EINVAL;
2226 } else {
2227 return 0;
2228 }
Amit Shekharfaefb322014-09-08 14:08:19 -07002229 } else if (audio_is_linear_pcm(out->format)) {
2230 *dsp_frames = out->written;
2231 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002232 } else
2233 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002234}
2235
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302236static int out_add_audio_effect(const struct audio_stream *stream __unused,
2237 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002238{
2239 return 0;
2240}
2241
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302242static int out_remove_audio_effect(const struct audio_stream *stream __unused,
2243 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002244{
2245 return 0;
2246}
2247
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302248static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
2249 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002250{
2251 return -EINVAL;
2252}
2253
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002254static int out_get_presentation_position(const struct audio_stream_out *stream,
2255 uint64_t *frames, struct timespec *timestamp)
2256{
2257 struct stream_out *out = (struct stream_out *)stream;
2258 int ret = -1;
Eric Laurent949a0892013-09-20 09:20:13 -07002259 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002260
Eric Laurent35455462015-06-19 16:30:44 -07002261 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002262
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002263 if (is_offload_usecase(out->usecase)) {
Eric Laurent949a0892013-09-20 09:20:13 -07002264 if (out->compr != NULL) {
2265 compress_get_tstamp(out->compr, &dsp_frames,
2266 &out->sample_rate);
2267 ALOGVV("%s rendered frames %ld sample_rate %d",
2268 __func__, dsp_frames, out->sample_rate);
2269 *frames = dsp_frames;
2270 ret = 0;
2271 /* this is the best we can do */
2272 clock_gettime(CLOCK_MONOTONIC, timestamp);
2273 }
2274 } else {
2275 if (out->pcm) {
2276 size_t avail;
2277 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
2278 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
Eric Laurent949a0892013-09-20 09:20:13 -07002279 int64_t signed_frames = out->written - kernel_buffer_size + avail;
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07002280 // This adjustment accounts for buffering after app processor.
2281 // It is based on estimated DSP latency per use case, rather than exact.
2282 signed_frames -=
2283 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
2284
Eric Laurent949a0892013-09-20 09:20:13 -07002285 // It would be unusual for this value to be negative, but check just in case ...
2286 if (signed_frames >= 0) {
2287 *frames = signed_frames;
2288 ret = 0;
2289 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07002290 }
2291 }
2292 }
2293
2294 pthread_mutex_unlock(&out->lock);
2295
2296 return ret;
2297}
2298
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002299static int out_set_callback(struct audio_stream_out *stream,
2300 stream_callback_t callback, void *cookie)
2301{
2302 struct stream_out *out = (struct stream_out *)stream;
2303
2304 ALOGV("%s", __func__);
Eric Laurent35455462015-06-19 16:30:44 -07002305 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002306 out->offload_callback = callback;
2307 out->offload_cookie = cookie;
2308 pthread_mutex_unlock(&out->lock);
2309 return 0;
2310}
2311
2312static int out_pause(struct audio_stream_out* stream)
2313{
2314 struct stream_out *out = (struct stream_out *)stream;
2315 int status = -ENOSYS;
2316 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002317 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302318 ALOGD("copl(%x):pause compress driver", (unsigned int)out);
Eric Laurent35455462015-06-19 16:30:44 -07002319 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002320 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302321 struct audio_device *adev = out->dev;
2322 int snd_scard_state = get_snd_card_state(adev);
2323
2324 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2325 status = compress_pause(out->compr);
2326
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002327 out->offload_state = OFFLOAD_STATE_PAUSED;
2328 }
2329 pthread_mutex_unlock(&out->lock);
2330 }
2331 return status;
2332}
2333
2334static int out_resume(struct audio_stream_out* stream)
2335{
2336 struct stream_out *out = (struct stream_out *)stream;
2337 int status = -ENOSYS;
2338 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002339 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302340 ALOGD("copl(%x):resume compress driver", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002341 status = 0;
Eric Laurent35455462015-06-19 16:30:44 -07002342 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002343 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302344 struct audio_device *adev = out->dev;
2345 int snd_scard_state = get_snd_card_state(adev);
2346
2347 if (SND_CARD_STATE_ONLINE == snd_scard_state)
2348 status = compress_resume(out->compr);
2349
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002350 out->offload_state = OFFLOAD_STATE_PLAYING;
2351 }
2352 pthread_mutex_unlock(&out->lock);
2353 }
2354 return status;
2355}
2356
2357static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
2358{
2359 struct stream_out *out = (struct stream_out *)stream;
2360 int status = -ENOSYS;
2361 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002362 if (is_offload_usecase(out->usecase)) {
Eric Laurent35455462015-06-19 16:30:44 -07002363 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002364 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
2365 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
2366 else
2367 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
2368 pthread_mutex_unlock(&out->lock);
2369 }
2370 return status;
2371}
2372
2373static int out_flush(struct audio_stream_out* stream)
2374{
2375 struct stream_out *out = (struct stream_out *)stream;
2376 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07002377 if (is_offload_usecase(out->usecase)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302378 ALOGD("copl(%x):calling compress flush", (unsigned int)out);
Eric Laurent35455462015-06-19 16:30:44 -07002379 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002380 stop_compressed_output_l(out);
2381 pthread_mutex_unlock(&out->lock);
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302382 ALOGD("copl(%x):out of compress flush", (unsigned int)out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002383 return 0;
2384 }
2385 return -ENOSYS;
2386}
2387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002388/** audio_stream_in implementation **/
2389static uint32_t in_get_sample_rate(const struct audio_stream *stream)
2390{
2391 struct stream_in *in = (struct stream_in *)stream;
2392
2393 return in->config.rate;
2394}
2395
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302396static int in_set_sample_rate(struct audio_stream *stream __unused,
2397 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002398{
2399 return -ENOSYS;
2400}
2401
2402static size_t in_get_buffer_size(const struct audio_stream *stream)
2403{
2404 struct stream_in *in = (struct stream_in *)stream;
2405
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002406 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
2407 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07002408 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
2409 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002410
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302411 return in->config.period_size *
Steve Kondik3abbbc82014-11-29 14:14:43 -08002412 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002413}
2414
2415static uint32_t in_get_channels(const struct audio_stream *stream)
2416{
2417 struct stream_in *in = (struct stream_in *)stream;
2418
2419 return in->channel_mask;
2420}
2421
2422static audio_format_t in_get_format(const struct audio_stream *stream)
2423{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002424 struct stream_in *in = (struct stream_in *)stream;
2425
2426 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002427}
2428
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302429static int in_set_format(struct audio_stream *stream __unused,
2430 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002431{
2432 return -ENOSYS;
2433}
2434
2435static int in_standby(struct audio_stream *stream)
2436{
2437 struct stream_in *in = (struct stream_in *)stream;
2438 struct audio_device *adev = in->dev;
2439 int status = 0;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302440 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
2441 stream, in->usecase, use_case_table[in->usecase]);
2442
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002443 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
2444 /* Ignore standby in case of voip call because the voip input
2445 * stream is closed in adev_close_input_stream()
2446 */
2447 ALOGV("%s: Ignore Standby in VOIP call", __func__);
2448 return status;
2449 }
2450
Eric Laurent35455462015-06-19 16:30:44 -07002451 lock_input_stream(in);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002452 if (!in->standby) {
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08002453 pthread_mutex_lock(&adev->lock);
Ethan Chen79c356c2015-06-07 12:26:14 -07002454
2455 amplifier_input_stream_standby((struct audio_stream_in *) stream);
2456
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002457 in->standby = true;
Eric Laurent150dbfe2013-02-27 14:31:02 -08002458 if (in->pcm) {
2459 pcm_close(in->pcm);
2460 in->pcm = NULL;
2461 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002462 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002463 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002464 }
2465 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07002466 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002467 return status;
2468}
2469
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302470static int in_dump(const struct audio_stream *stream __unused,
2471 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002472{
2473 return 0;
2474}
2475
2476static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
2477{
2478 struct stream_in *in = (struct stream_in *)stream;
2479 struct audio_device *adev = in->dev;
2480 struct str_parms *parms;
2481 char *str;
2482 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002483 int ret = 0, val = 0, err;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002484 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302486 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002487 parms = str_parms_create_str(kvpairs);
2488
Eric Laurent35455462015-06-19 16:30:44 -07002489 lock_input_stream(in);
2490
Eric Laurent150dbfe2013-02-27 14:31:02 -08002491 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08002492
2493 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
2494 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002495 val = atoi(value);
2496 /* no audio source uses val == 0 */
2497 if ((in->source != val) && (val != 0)) {
2498 in->source = val;
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002499 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2500 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
2501 (voice_extn_compress_voip_is_format_supported(in->format)) &&
2502 (in->config.rate == 8000 || in->config.rate == 16000) &&
Steve Kondikb6ab1fa2015-02-06 16:55:26 -08002503 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002504 err = voice_extn_compress_voip_open_input_stream(in);
2505 if (err != 0) {
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002506 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella287b8162014-02-04 16:23:52 -08002507 __func__, err);
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002508 }
2509 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002510 }
2511 }
2512
Steve Kondik3abbbc82014-11-29 14:14:43 -08002513 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
2514
2515 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002516 val = atoi(value);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302517 if (((int)in->device != val) && (val != 0)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002518 in->device = val;
2519 /* If recording is in progress, change the tx device to new device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002520 if (!in->standby)
Steve Kondik3abbbc82014-11-29 14:14:43 -08002521 status = select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002522 }
2523 }
2524
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08002525done:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002526 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08002527 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528
2529 str_parms_destroy(parms);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002530 ALOGV("%s: exit: status(%d)", __func__, status);
2531 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002532}
2533
2534static char* in_get_parameters(const struct audio_stream *stream,
2535 const char *keys)
2536{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002537 struct stream_in *in = (struct stream_in *)stream;
2538 struct str_parms *query = str_parms_create_str(keys);
2539 char *str;
2540 char value[256];
2541 struct str_parms *reply = str_parms_create();
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002542
2543 if (!query || !reply) {
2544 ALOGE("in_get_parameters: failed to create query or reply");
2545 return NULL;
2546 }
2547
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002548 ALOGV("%s: enter: keys - %s", __func__, keys);
2549
2550 voice_extn_in_get_parameters(in, query, reply);
2551
2552 str = str_parms_to_str(reply);
2553 str_parms_destroy(query);
2554 str_parms_destroy(reply);
2555
2556 ALOGV("%s: exit: returns - %s", __func__, str);
2557 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558}
2559
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302560static int in_set_gain(struct audio_stream_in *stream __unused,
2561 float gain __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002562{
2563 return 0;
2564}
2565
2566static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
2567 size_t bytes)
2568{
2569 struct stream_in *in = (struct stream_in *)stream;
2570 struct audio_device *adev = in->dev;
2571 int i, ret = -1;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302572 int snd_scard_state = get_snd_card_state(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002573
Eric Laurent35455462015-06-19 16:30:44 -07002574 lock_input_stream(in);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302575
2576 if (in->pcm) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302577 if(SND_CARD_STATE_OFFLINE == snd_scard_state) {
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302578 ALOGD(" %s: sound card is not active/SSR state", __func__);
2579 ret= -ENETRESET;
2580 goto exit;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302581 }
2582 }
2583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002584 if (in->standby) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002585 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002586 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
2587 ret = voice_extn_compress_voip_start_input_stream(in);
2588 else
2589 ret = start_input_stream(in);
Ethan Chen79c356c2015-06-07 12:26:14 -07002590
2591 if (ret == 0)
2592 amplifier_input_stream_start(stream);
2593
Eric Laurent150dbfe2013-02-27 14:31:02 -08002594 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002595 if (ret != 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002596 goto exit;
2597 }
2598 in->standby = 0;
2599 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002600
2601 if (in->pcm) {
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302602 if (audio_extn_ssr_get_enabled() &&
2603 audio_channel_count_from_in_mask(in->channel_mask) == 6)
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002604 ret = audio_extn_ssr_read(stream, buffer, bytes);
Mingming Yine62d7842013-10-25 16:26:03 -07002605 else if (audio_extn_compr_cap_usecase_supported(in->usecase))
2606 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302607 else if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY)
2608 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07002609 else
2610 ret = pcm_read(in->pcm, buffer, bytes);
Dhanalakshmi Siddani834b22f2014-08-20 12:28:34 +05302611 if (ret < 0)
2612 ret = -errno;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 }
2614
2615 /*
2616 * Instead of writing zeroes here, we could trust the hardware
2617 * to always provide zeroes when muted.
2618 */
Pavan Chikkala6c183fd2014-12-04 10:48:28 +05302619 if (ret == 0 && voice_get_mic_mute(adev) && !voice_is_in_call_rec_stream(in) &&
2620 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002621 memset(buffer, 0, bytes);
2622
2623exit:
Dhanalakshmi Siddani4fe3e512014-05-26 18:03:42 +05302624 /* ToDo: There may be a corner case when SSR happens back to back during
2625 start/stop. Need to post different error to handle that. */
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302626 if (-ENETRESET == ret) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05302627 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302628 memset(buffer, 0, bytes);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05302629 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002630 pthread_mutex_unlock(&in->lock);
2631
2632 if (ret != 0) {
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302633 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302634 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302635 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05302636 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Gutta369dd682014-06-25 20:38:03 +05302637 in->standby = true;
2638 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002639 in_standby(&in->stream.common);
2640 ALOGV("%s: read failed - sleeping for buffer duration", __func__);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002641 usleep(bytes * 1000000 / audio_stream_in_frame_size(stream) /
2642 in_get_sample_rate(&in->stream.common));
Andy Hung6cd0c612016-01-15 17:46:57 -08002643 } else {
2644 in->frames_read += bytes / audio_stream_in_frame_size(stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 }
2646 return bytes;
2647}
2648
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302649static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650{
2651 return 0;
2652}
2653
Andy Hung6cd0c612016-01-15 17:46:57 -08002654static int in_get_capture_position(const struct audio_stream_in *stream,
2655 int64_t *frames, int64_t *time)
2656{
2657 if (stream == NULL || frames == NULL || time == NULL) {
2658 return -EINVAL;
2659 }
2660 struct stream_in *in = (struct stream_in *)stream;
2661 int ret = -ENOSYS;
2662
2663 lock_input_stream(in);
2664 if (in->pcm) {
2665 struct timespec timestamp;
2666 unsigned int avail;
2667 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
2668 *frames = in->frames_read + avail;
2669 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
2670 ret = 0;
2671 }
2672 }
2673 pthread_mutex_unlock(&in->lock);
2674 return ret;
2675}
2676
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002677static int add_remove_audio_effect(const struct audio_stream *stream,
2678 effect_handle_t effect,
2679 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002680{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002681 struct stream_in *in = (struct stream_in *)stream;
2682 int status = 0;
2683 effect_descriptor_t desc;
2684
2685 status = (*effect)->get_descriptor(effect, &desc);
2686 if (status != 0)
2687 return status;
2688
Eric Laurent35455462015-06-19 16:30:44 -07002689 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002690 pthread_mutex_lock(&in->dev->lock);
2691 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
2692 in->enable_aec != enable &&
2693 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
2694 in->enable_aec = enable;
2695 if (!in->standby)
2696 select_devices(in->dev, in->usecase);
2697 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08002698 if (in->enable_ns != enable &&
2699 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
2700 in->enable_ns = enable;
2701 if (!in->standby)
2702 select_devices(in->dev, in->usecase);
2703 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002704 pthread_mutex_unlock(&in->dev->lock);
2705 pthread_mutex_unlock(&in->lock);
2706
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707 return 0;
2708}
2709
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002710static int in_add_audio_effect(const struct audio_stream *stream,
2711 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712{
Eric Laurent994a6932013-07-17 11:51:42 -07002713 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002714 return add_remove_audio_effect(stream, effect, true);
2715}
2716
2717static int in_remove_audio_effect(const struct audio_stream *stream,
2718 effect_handle_t effect)
2719{
Eric Laurent994a6932013-07-17 11:51:42 -07002720 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07002721 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002722}
2723
2724static int adev_open_output_stream(struct audio_hw_device *dev,
2725 audio_io_handle_t handle,
2726 audio_devices_t devices,
2727 audio_output_flags_t flags,
2728 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05302729 struct audio_stream_out **stream_out,
2730 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002731{
2732 struct audio_device *adev = (struct audio_device *)dev;
2733 struct stream_out *out;
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08002734 int i, ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002735
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002736 *stream_out = NULL;
Naresh Tannirucef332d2014-06-04 18:17:56 +05302737
2738 if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
2739 (SND_CARD_STATE_OFFLINE == get_snd_card_state(adev))) {
vivek mehtac2711cd2015-08-26 14:01:20 -07002740 ALOGE("sound card is not active rejecting compress output open request");
Naresh Tannirucef332d2014-06-04 18:17:56 +05302741 return -EINVAL;
2742 }
2743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
2745
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05302746 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
2747 stream_handle(%p)",__func__, config->sample_rate, config->channel_mask,
2748 devices, flags, &out->stream);
2749
2750
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002751 if (!out) {
2752 return -ENOMEM;
2753 }
2754
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002755 if (devices == AUDIO_DEVICE_NONE)
2756 devices = AUDIO_DEVICE_OUT_SPEAKER;
2757
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002758 out->flags = flags;
2759 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07002760 out->dev = adev;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002761 out->format = config->format;
2762 out->sample_rate = config->sample_rate;
2763 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
2764 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
Eric Laurentc4aef752013-09-12 17:45:53 -07002765 out->handle = handle;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002766 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002767 out->non_blocking = 0;
2768 out->use_small_bufs = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769
2770 /* Init use case and pcm_config */
Mingming Yin8cde13d2015-07-21 15:22:22 -07002771 if ((out->flags & AUDIO_OUTPUT_FLAG_DIRECT) &&
2772 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Mingming Yinee733602014-04-03 17:47:22 -07002773 (
2774#ifdef AFE_PROXY_ENABLED
2775 out->devices & AUDIO_DEVICE_OUT_PROXY ||
2776#endif
2777 out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002778
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002779 pthread_mutex_lock(&adev->lock);
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002780 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
2781 ret = read_hdmi_channel_masks(out);
2782
Mingming Yinee733602014-04-03 17:47:22 -07002783#ifdef AFE_PROXY_ENABLED
Apoorv Raghuvanshi947cb902013-12-09 13:45:39 -08002784 if (out->devices & AUDIO_DEVICE_OUT_PROXY)
2785 ret = audio_extn_read_afe_proxy_channel_masks(out);
Mingming Yinee733602014-04-03 17:47:22 -07002786#endif
2787
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002788 pthread_mutex_unlock(&adev->lock);
Eric Laurent07eeafd2013-10-06 12:52:49 -07002789 if (ret != 0)
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002790 goto error_open;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002791
2792 if (config->sample_rate == 0)
2793 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2794 if (config->channel_mask == 0)
2795 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
2796
2797 out->channel_mask = config->channel_mask;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002798 out->sample_rate = config->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002799 out->usecase = USECASE_AUDIO_PLAYBACK_MULTI_CH;
2800 out->config = pcm_config_hdmi_multi;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002801 out->config.rate = config->sample_rate;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302802 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002803 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels * 2);
Mingming Yinee733602014-04-03 17:47:22 -07002804#ifdef COMPRESS_VOIP_ENABLED
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002805 } else if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Scott Mertz624f14f2016-04-05 12:40:11 -07002806 ((out->flags & ~AUDIO_OUTPUT_FLAG_RAW) ==
2807 (AUDIO_OUTPUT_FLAG_DIRECT | AUDIO_OUTPUT_FLAG_VOIP_RX)) &&
Narsinga Rao Chella1eceff82013-12-02 19:25:28 -08002808 (voice_extn_compress_voip_is_config_supported(config))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002809 ret = voice_extn_compress_voip_open_output_stream(out);
2810 if (ret != 0) {
2811 ALOGE("%s: Compress voip output cannot be opened, error:%d",
2812 __func__, ret);
2813 goto error_open;
2814 }
Mingming Yinee733602014-04-03 17:47:22 -07002815#endif
vivek mehtac2711cd2015-08-26 14:01:20 -07002816 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
2817 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM)) {
Sidipotu Ashok5bfacf72014-02-10 16:16:38 +05302818 ALOGD("%s: copl(%x): sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)",
2819 __func__, (unsigned int)out, config->sample_rate, config->channel_mask, devices, flags);
2820
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002821 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
2822 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
2823 ALOGE("%s: Unsupported Offload information", __func__);
2824 ret = -EINVAL;
2825 goto error_open;
2826 }
Mingming Yin90310102013-11-13 16:57:00 -08002827 if (!is_supported_format(config->offload_info.format) &&
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002828 !audio_extn_is_dolby_format(config->offload_info.format)) {
vivek mehtac2711cd2015-08-26 14:01:20 -07002829 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002830 ret = -EINVAL;
2831 goto error_open;
2832 }
2833
2834 out->compr_config.codec = (struct snd_codec *)
2835 calloc(1, sizeof(struct snd_codec));
2836
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07002837 if (!out->compr_config.codec) {
2838 ret = -ENOMEM;
2839 goto error_open;
2840 }
2841
vivek mehtac2711cd2015-08-26 14:01:20 -07002842 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) {
2843 ALOGV("%s:: inserting DIRECT_PCM _USECASE", __func__);
2844 out->usecase = USECASE_AUDIO_DIRECT_PCM_OFFLOAD;
2845 } else {
2846 ALOGV("%s:: inserting OFFLOAD_USECASE", __func__);
2847 out->usecase = get_offload_usecase(adev);
Amit Shekharfaefb322014-09-08 14:08:19 -07002848
2849 out->stream.set_callback = out_set_callback;
2850 out->stream.pause = out_pause;
2851 out->stream.resume = out_resume;
2852 out->stream.drain = out_drain;
2853 out->stream.flush = out_flush;
vivek mehtac2711cd2015-08-26 14:01:20 -07002854 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002855 if (config->offload_info.channel_mask)
2856 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002857 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002858 out->channel_mask = config->channel_mask;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002859 config->offload_info.channel_mask = config->channel_mask;
2860 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002861 out->format = config->offload_info.format;
2862 out->sample_rate = config->offload_info.sample_rate;
2863
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002864 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002865
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002866 if (audio_extn_is_dolby_format(config->offload_info.format))
Mingming Yin90310102013-11-13 16:57:00 -08002867 out->compr_config.codec->id =
Subhash Chandra Bose Naripeddye0a07122013-12-14 00:34:53 -08002868 audio_extn_dolby_get_snd_codec_id(adev, out,
2869 config->offload_info.format);
Mingming Yin90310102013-11-13 16:57:00 -08002870 else
2871 out->compr_config.codec->id =
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002872 get_snd_codec_id(config->offload_info.format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002873
vivek mehtac2711cd2015-08-26 14:01:20 -07002874 if (((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM_OFFLOAD)||
2875 ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_PCM)) {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002876 out->compr_config.fragment_size =
2877 platform_get_pcm_offload_buffer_size(&config->offload_info);
Steve Kondik3abbbc82014-11-29 14:14:43 -08002878 } else {
ApurupaPattapu0c566872014-01-10 14:46:02 -08002879 out->compr_config.fragment_size =
2880 platform_get_compress_offload_buffer_size(&config->offload_info);
2881 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002882 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
Eric Laurent0043e152014-10-23 14:42:59 -07002883#ifdef NEW_SAMPLE_RATE_ENABLED
2884 out->compr_config.codec->sample_rate = config->offload_info.sample_rate;
2885#else
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002886 out->compr_config.codec->sample_rate =
2887 compress_get_alsa_rate(config->offload_info.sample_rate);
Eric Laurent0043e152014-10-23 14:42:59 -07002888#endif
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002889 out->compr_config.codec->bit_rate =
2890 config->offload_info.bit_rate;
2891 out->compr_config.codec->ch_in =
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05302892 audio_channel_count_from_out_mask(config->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002893 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Amit Shekharfaefb322014-09-08 14:08:19 -07002894 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
2895 /*TODO: Do we need to change it for passthrough */
2896 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002897
Steve Kondik3fdf4fc2014-12-10 21:15:43 -08002898 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
Steve Kondik37454012014-11-23 19:54:21 -08002899 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
ApurupaPattapu0c566872014-01-10 14:46:02 -08002900 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT_OFFLOAD)
2901 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002902 if (config->offload_info.format == AUDIO_FORMAT_PCM_24_BIT_OFFLOAD)
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002903 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
vivek mehtac2711cd2015-08-26 14:01:20 -07002904 if (config->offload_info.format == AUDIO_FORMAT_PCM_16_BIT)
2905 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S16_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002906
Steve Kondik3abbbc82014-11-29 14:14:43 -08002907 if (out->bit_width == 24)
2908 out->compr_config.codec->format = SNDRV_PCM_FORMAT_S24_LE;
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002909
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002910#ifdef FLAC_OFFLOAD_ENABLED
Steve Kondik37454012014-11-23 19:54:21 -08002911 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Amit Shekharfaefb322014-09-08 14:08:19 -07002912 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Steve Kondik6bedcdf2014-07-21 11:48:30 -07002913#endif
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08002914
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002915 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
2916 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002917
Mingming Yind48310a2015-06-10 16:28:10 -07002918 if (platform_use_small_buffer(&config->offload_info)) {
Alexy Joseph3a2fec32014-12-03 02:46:47 -08002919 //this flag is set from framework only if its for PCM formats
2920 //no need to check for PCM format again
2921 out->non_blocking = 0;
2922 out->use_small_bufs = true;
2923 ALOGI("Keep write blocking for small buff: non_blockling %d",
2924 out->non_blocking);
2925 }
2926
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002927 out->send_new_metadata = 1;
Alexy Joseph505da3f2015-09-10 01:31:51 -07002928 out->send_next_track_params = false;
2929 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08002930 out->offload_state = OFFLOAD_STATE_IDLE;
2931 out->playback_started = 0;
2932
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002933 create_offload_callback_thread(out);
2934 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
2935 __func__, config->offload_info.version,
2936 config->offload_info.bit_rate);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002937 //Decide if we need to use gapless mode by default
Krishnankutty Kolathappilly9d1632f2014-01-09 12:45:31 -08002938 check_and_set_gapless_mode(adev);
Krishnankutty Kolathappillyb165a8a2014-01-07 11:25:51 -08002939
Mingming Yinee733602014-04-03 17:47:22 -07002940#ifdef INCALL_MUSIC_ENABLED
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07002941 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
2942 ret = voice_check_and_set_incall_music_usecase(adev, out);
2943 if (ret != 0) {
2944 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
2945 __func__, ret);
2946 goto error_open;
2947 }
Mingming Yinee733602014-04-03 17:47:22 -07002948#endif
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05302949 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
2950 if (config->sample_rate == 0)
2951 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2952 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
2953 config->sample_rate != 8000) {
2954 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
2955 ret = -EINVAL;
2956 goto error_open;
2957 }
2958 out->sample_rate = config->sample_rate;
2959 out->config.rate = config->sample_rate;
2960 if (config->format == AUDIO_FORMAT_DEFAULT)
2961 config->format = AUDIO_FORMAT_PCM_16_BIT;
2962 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
2963 config->format = AUDIO_FORMAT_PCM_16_BIT;
2964 ret = -EINVAL;
2965 goto error_open;
2966 }
2967 out->format = config->format;
2968 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
2969 out->config = pcm_config_afe_proxy_playback;
2970 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07002971 } else {
Steve Kondik26d44522015-12-16 15:23:47 -05002972 if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
2973 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
2974 out->config = pcm_config_deep_buffer;
2975 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ravi Kumar Alamanda8c884872015-06-25 20:08:01 -07002976 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
2977 out->config = pcm_config_low_latency;
Amit Shekharfaefb322014-09-08 14:08:19 -07002978 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
2979 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
2980 out->config = pcm_config_low_latency;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002981 } else {
2982 /* primary path is the default path selected if no other outputs are available/suitable */
2983 out->usecase = USECASE_AUDIO_PLAYBACK_PRIMARY;
Amit Shekharfaefb322014-09-08 14:08:19 -07002984 out->config = PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY;
Steve Kondik3abbbc82014-11-29 14:14:43 -08002985 }
Amit Shekharfaefb322014-09-08 14:08:19 -07002986
Steve Kondik3abbbc82014-11-29 14:14:43 -08002987 if (config->format != audio_format_from_pcm_format(out->config.format)) {
2988 if (k_enable_extended_precision
2989 && pcm_params_format_test(adev->use_case_table[out->usecase],
2990 pcm_format_from_audio_format(config->format))) {
2991 out->config.format = pcm_format_from_audio_format(config->format);
2992 /* out->format already set to config->format */
2993 } else {
2994 /* deny the externally proposed config format
2995 * and use the one specified in audio_hw layer configuration.
2996 * Note: out->format is returned by out->stream.common.get_format()
2997 * and is used to set config->format in the code several lines below.
2998 */
Steve Kondik5a447012014-12-02 16:04:20 -08002999 ALOGW("Audio format %x is not available on this output", out->format);
Steve Kondik3abbbc82014-11-29 14:14:43 -08003000 out->format = audio_format_from_pcm_format(out->config.format);
3001 }
3002 }
3003
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07003004 out->sample_rate = out->config.rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003005 }
3006
Amit Shekharfaefb322014-09-08 14:08:19 -07003007 ALOGV("%s devices %d,flags %x, format %x, out->sample_rate %d, out->bit_width %d",
3008 __func__, devices, flags, out->format, out->sample_rate, out->bit_width);
Steve Kondik5a447012014-12-02 16:04:20 -08003009
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003010 if ((out->usecase == USECASE_AUDIO_PLAYBACK_PRIMARY) ||
Steve Kondik3abbbc82014-11-29 14:14:43 -08003011 flags & AUDIO_OUTPUT_FLAG_PRIMARY) {
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08003012 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003013 if(adev->primary_output == NULL)
3014 adev->primary_output = out;
3015 else {
3016 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003017 ret = -EEXIST;
3018 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003019 }
3020 }
3021
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 /* Check if this usecase is already existing */
3023 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella0d06c8e2014-04-17 20:00:41 -07003024 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
3025 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003026 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003027 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003028 ret = -EEXIST;
3029 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 }
3031 pthread_mutex_unlock(&adev->lock);
3032
3033 out->stream.common.get_sample_rate = out_get_sample_rate;
3034 out->stream.common.set_sample_rate = out_set_sample_rate;
3035 out->stream.common.get_buffer_size = out_get_buffer_size;
3036 out->stream.common.get_channels = out_get_channels;
3037 out->stream.common.get_format = out_get_format;
3038 out->stream.common.set_format = out_set_format;
3039 out->stream.common.standby = out_standby;
3040 out->stream.common.dump = out_dump;
3041 out->stream.common.set_parameters = out_set_parameters;
3042 out->stream.common.get_parameters = out_get_parameters;
3043 out->stream.common.add_audio_effect = out_add_audio_effect;
3044 out->stream.common.remove_audio_effect = out_remove_audio_effect;
3045 out->stream.get_latency = out_get_latency;
3046 out->stream.set_volume = out_set_volume;
3047 out->stream.write = out_write;
3048 out->stream.get_render_position = out_get_render_position;
3049 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003050 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003051
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003052 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07003053 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07003054 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003055
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303056 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurent35455462015-06-19 16:30:44 -07003057 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303058 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
3059
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003060 config->format = out->stream.common.get_format(&out->stream.common);
3061 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
3062 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
3063
3064 *stream_out = &out->stream;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303065 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehtac2711cd2015-08-26 14:01:20 -07003066 use_case_table[out->usecase]);
3067
Eric Laurent994a6932013-07-17 11:51:42 -07003068 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003069 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07003070
3071error_open:
3072 free(out);
3073 *stream_out = NULL;
3074 ALOGD("%s: exit: ret %d", __func__, ret);
3075 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003076}
3077
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303078static void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079 struct audio_stream_out *stream)
3080{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003081 struct stream_out *out = (struct stream_out *)stream;
3082 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003083 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003084
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303085 ALOGD("%s: enter:stream_handle(%p)",__func__, out);
3086
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003087 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Divya Narayanan Poojary98180cc2016-03-11 16:55:13 +05303088 pthread_mutex_lock(&out->lock);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303089 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003090 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303091 pthread_mutex_unlock(&adev->lock);
Divya Narayanan Poojary98180cc2016-03-11 16:55:13 +05303092 pthread_mutex_unlock(&out->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003093 if(ret != 0)
3094 ALOGE("%s: Compress voip output cannot be closed, error:%d",
3095 __func__, ret);
3096 }
3097 else
3098 out_standby(&stream->common);
3099
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003100 if (is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003101 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003102 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003103 if (out->compr_config.codec != NULL)
3104 free(out->compr_config.codec);
3105 }
3106 pthread_cond_destroy(&out->cond);
3107 pthread_mutex_destroy(&out->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003108 free(stream);
Eric Laurent994a6932013-07-17 11:51:42 -07003109 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003110}
3111
Alexy Joseph55204352014-10-06 12:15:01 -07003112static void close_compress_sessions(struct audio_device *adev)
3113{
3114 struct stream_out *out = NULL;
3115 struct listnode *node = NULL;
3116 struct listnode *tmp = NULL;
3117 struct audio_usecase *usecase = NULL;
3118 pthread_mutex_lock(&adev->lock);
3119 list_for_each_safe(node, tmp, &adev->usecase_list) {
3120 usecase = node_to_item(node, struct audio_usecase, list);
3121 if (is_offload_usecase(usecase->id)) {
3122 if (usecase && usecase->stream.out) {
3123 ALOGI(" %s closing compress session %d on OFFLINE state", __func__, usecase->id);
3124 out = usecase->stream.out;
3125 pthread_mutex_unlock(&adev->lock);
3126 out_standby(&out->stream.common);
3127 pthread_mutex_lock(&adev->lock);
3128 }
3129 }
3130 }
3131 pthread_mutex_unlock(&adev->lock);
3132}
3133
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
3135{
3136 struct audio_device *adev = (struct audio_device *)dev;
3137 struct str_parms *parms;
3138 char *str;
3139 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003140 int val;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303141 int ret;
3142 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003143
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003144 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003145 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003146
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303147 ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
3148 if (ret >= 0) {
3149 char *snd_card_status = value+2;
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303150 if (strstr(snd_card_status, "OFFLINE")) {
Naresh Tannirucef332d2014-06-04 18:17:56 +05303151 struct listnode *node;
3152 struct audio_usecase *usecase;
3153
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303154 ALOGD("Received sound card OFFLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303155 set_snd_card_state(adev,SND_CARD_STATE_OFFLINE);
3156
Alexy Joseph55204352014-10-06 12:15:01 -07003157 //close compress sessions on OFFLINE status
3158 close_compress_sessions(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303159 } else if (strstr(snd_card_status, "ONLINE")) {
3160 ALOGD("Received sound card ONLINE status");
Naresh Tannirucef332d2014-06-04 18:17:56 +05303161 set_snd_card_state(adev,SND_CARD_STATE_ONLINE);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303162 }
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303163 }
3164
3165 pthread_mutex_lock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303166 status = voice_set_parameters(adev, parms);
3167 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003168 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003169
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303170 status = platform_set_parameters(adev->platform, parms);
3171 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003172 goto done;
3173
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303174 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
3175 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003176 /* When set to false, HAL should disable EC and NS
3177 * But it is currently not supported.
3178 */
3179 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3180 adev->bluetooth_nrec = true;
3181 else
3182 adev->bluetooth_nrec = false;
3183 }
3184
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303185 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
3186 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
3188 adev->screen_off = false;
3189 else
3190 adev->screen_off = true;
3191 }
3192
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303193 ret = str_parms_get_int(parms, "rotation", &val);
3194 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003195 bool reverse_speakers = false;
3196 switch(val) {
3197 // FIXME: note that the code below assumes that the speakers are in the correct placement
3198 // relative to the user when the device is rotated 90deg from its default rotation. This
3199 // assumption is device-specific, not platform-specific like this code.
3200 case 270:
3201 reverse_speakers = true;
3202 break;
3203 case 0:
3204 case 90:
3205 case 180:
3206 break;
3207 default:
3208 ALOGE("%s: unexpected rotation of %d", __func__, val);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303209 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003210 }
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303211 if (status == 0) {
3212 if (adev->speaker_lr_swap != reverse_speakers) {
3213 adev->speaker_lr_swap = reverse_speakers;
3214 // only update the selected device if there is active pcm playback
3215 struct audio_usecase *usecase;
3216 struct listnode *node;
3217 list_for_each(node, &adev->usecase_list) {
3218 usecase = node_to_item(node, struct audio_usecase, list);
3219 if (usecase->type == PCM_PLAYBACK) {
Steve Kondik3abbbc82014-11-29 14:14:43 -08003220 status = select_devices(adev, usecase->id);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303221 break;
3222 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003223 }
3224 }
3225 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07003226 }
3227
LiuShangfe0bc342015-02-17 18:20:11 +08003228 /* Microphone selection in test mode */
3229 ret = str_parms_get_str(parms, FP_TEST_KEY, value, sizeof(value));
3230 if (ret >= 0) {
3231 if (strncmp(FP_TEST_KEY_PRIMARY, value, sizeof(value)) == 0) {
3232 ALOGD("FP test requests primary mic.");
3233 mFpTestMicSource = FP_TEST_PRIMARY_MIC;
3234 } else if (strncmp(FP_TEST_KEY_SECONDARY, value, sizeof(value)) == 0) {
3235 ALOGD("FP test requests secondary mic.");
3236 mFpTestMicSource = FP_TEST_SECONDARY_MIC;
3237 } else {
3238 ALOGD("FP test requests to be disabled");
3239 mFpTestMicSource = FP_TEST_DEFAULT_MIC;
3240 }
3241 }
3242
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003243 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003244
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08003245done:
3246 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003247 pthread_mutex_unlock(&adev->lock);
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303248 ALOGV("%s: exit with code(%d)", __func__, status);
3249 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003250}
3251
3252static char* adev_get_parameters(const struct audio_hw_device *dev,
3253 const char *keys)
3254{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003255 struct audio_device *adev = (struct audio_device *)dev;
3256 struct str_parms *reply = str_parms_create();
3257 struct str_parms *query = str_parms_create_str(keys);
3258 char *str;
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303259 char value[256] = {0};
3260 int ret = 0;
3261
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003262 if (!query || !reply) {
3263 ALOGE("adev_get_parameters: failed to create query or reply");
3264 return NULL;
3265 }
3266
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303267 ret = str_parms_get_str(query, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, value,
3268 sizeof(value));
3269 if (ret >=0) {
3270 int val = 1;
3271 pthread_mutex_lock(&adev->snd_card_status.lock);
3272 if (SND_CARD_STATE_OFFLINE == adev->snd_card_status.state)
3273 val = 0;
3274 pthread_mutex_unlock(&adev->snd_card_status.lock);
3275 str_parms_add_int(reply, AUDIO_PARAMETER_KEY_SND_CARD_STATUS, val);
3276 goto exit;
3277 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003278
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003279 pthread_mutex_lock(&adev->lock);
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303280
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003281 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08003282 voice_get_parameters(adev, query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003283 platform_get_parameters(adev->platform, query, reply);
Naresh Tannirucef332d2014-06-04 18:17:56 +05303284 pthread_mutex_unlock(&adev->lock);
3285
Naresh Tanniruc6ca6352014-06-20 02:54:48 +05303286exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003287 str = str_parms_to_str(reply);
3288 str_parms_destroy(query);
3289 str_parms_destroy(reply);
3290
3291 ALOGV("%s: exit: returns - %s", __func__, str);
3292 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293}
3294
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303295static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296{
3297 return 0;
3298}
3299
3300static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
3301{
Haynes Mathew George5191a852013-09-11 14:19:36 -07003302 int ret;
3303 struct audio_device *adev = (struct audio_device *)dev;
Eric Laurent321b96d2014-09-10 13:21:01 -05003304
3305 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
3306
Haynes Mathew George5191a852013-09-11 14:19:36 -07003307 pthread_mutex_lock(&adev->lock);
3308 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07003309 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07003310 pthread_mutex_unlock(&adev->lock);
3311 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003312}
3313
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303314static int adev_set_master_volume(struct audio_hw_device *dev __unused,
3315 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316{
3317 return -ENOSYS;
3318}
3319
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303320static int adev_get_master_volume(struct audio_hw_device *dev __unused,
3321 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003322{
3323 return -ENOSYS;
3324}
3325
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303326static int adev_set_master_mute(struct audio_hw_device *dev __unused,
3327 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003328{
3329 return -ENOSYS;
3330}
3331
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303332static int adev_get_master_mute(struct audio_hw_device *dev __unused,
3333 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334{
3335 return -ENOSYS;
3336}
3337
3338static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
3339{
3340 struct audio_device *adev = (struct audio_device *)dev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 pthread_mutex_lock(&adev->lock);
3342 if (adev->mode != mode) {
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07003343 ALOGD("%s mode %d\n", __func__, mode);
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303344 if (amplifier_set_mode(mode) != 0)
3345 ALOGE("Failed setting amplifier mode");
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346 adev->mode = mode;
3347 }
3348 pthread_mutex_unlock(&adev->lock);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003349
3350 audio_extn_extspk_set_mode(adev->extspk, mode);
3351
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003352 return 0;
3353}
3354
3355static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
3356{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003357 int ret;
3358
3359 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003360 ALOGD("%s state %d\n", __func__, state);
Shreyas Nagasandra Chandrasekhar9781c6c2014-12-01 05:49:35 -08003361 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08003362 pthread_mutex_unlock(&adev->lock);
3363
3364 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003365}
3366
3367static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
3368{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003369 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003370 return 0;
3371}
3372
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303373static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 const struct audio_config *config)
3375{
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303376 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003377
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003378 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
3379 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380}
3381
3382static int adev_open_input_stream(struct audio_hw_device *dev,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303383 audio_io_handle_t handle __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384 audio_devices_t devices,
3385 struct audio_config *config,
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303386 struct audio_stream_in **stream_in,
3387 audio_input_flags_t flags __unused,
3388 const char *address __unused,
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003389 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003390{
3391 struct audio_device *adev = (struct audio_device *)dev;
3392 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003393 int ret = 0, buffer_size, frame_size;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303394 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003395 bool is_low_latency = false;
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003397 *stream_in = NULL;
3398 if (check_input_parameters(config->sample_rate, config->format, channel_count) != 0)
3399 return -EINVAL;
3400
3401 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003402
3403 if (!in) {
3404 ALOGE("failed to allocate input stream");
3405 return -ENOMEM;
3406 }
3407
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303408 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003409 stream_handle(%p) io_handle(%d) source(%d)",__func__, config->sample_rate, config->channel_mask,
3410 devices, &in->stream, handle, source);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003411
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003412 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Eric Laurent35455462015-06-19 16:30:44 -07003413 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003414
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003415 in->stream.common.get_sample_rate = in_get_sample_rate;
3416 in->stream.common.set_sample_rate = in_set_sample_rate;
3417 in->stream.common.get_buffer_size = in_get_buffer_size;
3418 in->stream.common.get_channels = in_get_channels;
3419 in->stream.common.get_format = in_get_format;
3420 in->stream.common.set_format = in_set_format;
3421 in->stream.common.standby = in_standby;
3422 in->stream.common.dump = in_dump;
3423 in->stream.common.set_parameters = in_set_parameters;
3424 in->stream.common.get_parameters = in_get_parameters;
3425 in->stream.common.add_audio_effect = in_add_audio_effect;
3426 in->stream.common.remove_audio_effect = in_remove_audio_effect;
3427 in->stream.set_gain = in_set_gain;
3428 in->stream.read = in_read;
3429 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Andy Hung6cd0c612016-01-15 17:46:57 -08003430 in->stream.get_capture_position = in_get_capture_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003431
3432 in->device = devices;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003433 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003434 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003435 in->standby = 1;
3436 in->channel_mask = config->channel_mask;
Andy Hung6cd0c612016-01-15 17:46:57 -08003437 // in->frames_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003438
3439 /* Update config params with the requested sample rate and channels */
3440 in->usecase = USECASE_AUDIO_RECORD;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003441 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
3442 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
3443 is_low_latency = true;
3444#if LOW_LATENCY_CAPTURE_USE_CASE
3445 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
3446#endif
3447 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003448 in->config = pcm_config_audio_capture;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 in->config.rate = config->sample_rate;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003450 in->format = config->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003451
Scott Mertz8e017862016-03-16 09:31:48 -07003452 if (in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) {
Pavan Chikkala3c0036d2014-12-17 16:45:10 +05303453 if (adev->mode != AUDIO_MODE_IN_CALL) {
3454 ret = -EINVAL;
3455 goto err_open;
Pavan Chikkala3ec42ef2014-11-21 20:57:48 +05303456 }
Divya Narayanan Poojaryab9b1ef2014-09-12 15:52:36 +05303457 if (config->sample_rate == 0)
3458 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3459 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
3460 config->sample_rate != 8000) {
3461 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
3462 ret = -EINVAL;
3463 goto err_open;
3464 }
3465 if (config->format == AUDIO_FORMAT_DEFAULT)
3466 config->format = AUDIO_FORMAT_PCM_16_BIT;
3467 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
3468 config->format = AUDIO_FORMAT_PCM_16_BIT;
3469 ret = -EINVAL;
3470 goto err_open;
3471 }
3472 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
3473 in->config = pcm_config_afe_proxy_record;
3474 in->config.channels = channel_count;
3475 in->config.rate = config->sample_rate;
3476 } else if (channel_count == 6) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003477 if(audio_extn_ssr_get_enabled()) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303478 if(audio_extn_ssr_init(in)) {
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003479 ALOGE("%s: audio_extn_ssr_init failed", __func__);
3480 ret = -EINVAL;
3481 goto err_open;
3482 }
3483 } else {
Mingming Yindaf9c542014-09-16 17:41:33 -07003484 ALOGW("%s: surround sound recording is not supported", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003485 }
Mingming Yine62d7842013-10-25 16:26:03 -07003486 } else if (audio_extn_compr_cap_enabled() &&
Narsinga Rao Chellab0668ee2014-01-24 15:33:23 -08003487 audio_extn_compr_cap_format_supported(config->format) &&
3488 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303489 audio_extn_compr_cap_init(in);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003490 } else {
3491 in->config.channels = channel_count;
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303492 frame_size = audio_stream_in_frame_size(&in->stream);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003493 buffer_size = get_input_buffer_size(config->sample_rate,
3494 config->format,
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003495 channel_count,
3496 is_low_latency);
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003497 in->config.period_size = buffer_size / frame_size;
Vidyakumar Athota7e6ba2e2015-03-31 21:53:21 -07003498 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
3499 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
3500 (voice_extn_compress_voip_is_format_supported(in->format)) &&
3501 (in->config.rate == 8000 || in->config.rate == 16000) &&
3502 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
3503 voice_extn_compress_voip_open_input_stream(in);
3504 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003505 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003506
3507 *stream_in = &in->stream;
Eric Laurent994a6932013-07-17 11:51:42 -07003508 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003509 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003510
3511err_open:
3512 free(in);
3513 *stream_in = NULL;
3514 return ret;
3515}
3516
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303517static void adev_close_input_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 struct audio_stream_in *stream)
3519{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003520 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003521 struct stream_in *in = (struct stream_in *)stream;
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303522 struct audio_device *adev = in->dev;
3523
Sidipotu Ashoke4514fa2014-05-02 16:21:50 +05303524 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003525
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003526 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Divya Narayanan Poojary98180cc2016-03-11 16:55:13 +05303527 pthread_mutex_lock(&in->lock);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303528 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003529 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta593b7c12014-08-11 18:20:49 +05303530 pthread_mutex_unlock(&adev->lock);
Divya Narayanan Poojary98180cc2016-03-11 16:55:13 +05303531 pthread_mutex_unlock(&in->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003532 if (ret != 0)
3533 ALOGE("%s: Compress voip input cannot be closed, error:%d",
3534 __func__, ret);
3535 } else
3536 in_standby(&stream->common);
3537
Divya Narayanan Poojary69236ba2014-09-18 11:57:57 +05303538 if (audio_extn_ssr_get_enabled() &&
3539 (audio_channel_count_from_in_mask(in->channel_mask) == 6)) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07003540 audio_extn_ssr_deinit();
3541 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542 free(stream);
3543
Mingming Yine62d7842013-10-25 16:26:03 -07003544 if(audio_extn_compr_cap_enabled() &&
3545 audio_extn_compr_cap_format_supported(in->config.format))
3546 audio_extn_compr_cap_deinit();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003547 return;
3548}
3549
Divya Narayanan Poojarybd9f33f2014-09-17 17:35:59 +05303550static int adev_dump(const audio_hw_device_t *device __unused,
3551 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003552{
3553 return 0;
3554}
3555
Steve Kondik3abbbc82014-11-29 14:14:43 -08003556/* verifies input and output devices and their capabilities.
3557 *
3558 * This verification is required when enabling extended bit-depth or
3559 * sampling rates, as not all qcom products support it.
3560 *
3561 * Suitable for calling only on initialization such as adev_open().
3562 * It fills the audio_device use_case_table[] array.
3563 *
3564 * Has a side-effect that it needs to configure audio routing / devices
3565 * in order to power up the devices and read the device parameters.
3566 * It does not acquire any hw device lock. Should restore the devices
3567 * back to "normal state" upon completion.
3568 */
3569static int adev_verify_devices(struct audio_device *adev)
3570{
3571 /* enumeration is a bit difficult because one really wants to pull
3572 * the use_case, device id, etc from the hidden pcm_device_table[].
3573 * In this case there are the following use cases and device ids.
3574 *
3575 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
3576 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
3577 * [USECASE_AUDIO_PLAYBACK_MULTI_CH] = {1, 1},
3578 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
3579 * [USECASE_AUDIO_RECORD] = {0, 0},
3580 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
3581 * [USECASE_VOICE_CALL] = {2, 2},
3582 *
3583 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_MULTI_CH omitted.
3584 * USECASE_VOICE_CALL omitted, but possible for either input or output.
3585 */
3586
3587 /* should be the usecases enabled in adev_open_input_stream() */
3588 static const int test_in_usecases[] = {
3589 USECASE_AUDIO_RECORD,
3590 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
3591 };
3592 /* should be the usecases enabled in adev_open_output_stream()*/
3593 static const int test_out_usecases[] = {
3594 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
3595 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
3596 };
3597 static const usecase_type_t usecase_type_by_dir[] = {
3598 PCM_PLAYBACK,
3599 PCM_CAPTURE,
3600 };
3601 static const unsigned flags_by_dir[] = {
3602 PCM_OUT,
3603 PCM_IN,
3604 };
3605
3606 size_t i;
3607 unsigned dir;
3608 const unsigned card_id = adev->snd_card;
3609 char info[512]; /* for possible debug info */
3610
3611 for (dir = 0; dir < 2; ++dir) {
3612 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
3613 const unsigned flags_dir = flags_by_dir[dir];
3614 const size_t testsize =
3615 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
3616 const int *testcases =
3617 dir ? test_in_usecases : test_out_usecases;
3618 const audio_devices_t audio_device =
3619 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
3620
3621 for (i = 0; i < testsize; ++i) {
3622 const audio_usecase_t audio_usecase = testcases[i];
3623 int device_id;
3624 snd_device_t snd_device;
3625 struct pcm_params **pparams;
3626 struct stream_out out;
3627 struct stream_in in;
3628 struct audio_usecase uc_info;
3629 int retval;
3630
3631 pparams = &adev->use_case_table[audio_usecase];
3632 pcm_params_free(*pparams); /* can accept null input */
3633 *pparams = NULL;
3634
3635 /* find the device ID for the use case (signed, for error) */
3636 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
3637 if (device_id < 0)
3638 continue;
3639
3640 /* prepare structures for device probing */
3641 memset(&uc_info, 0, sizeof(uc_info));
3642 uc_info.id = audio_usecase;
3643 uc_info.type = usecase_type;
3644 if (dir) {
3645 adev->active_input = &in;
3646 memset(&in, 0, sizeof(in));
3647 in.device = audio_device;
3648 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
3649 uc_info.stream.in = &in;
3650 } else {
3651 adev->active_input = NULL;
3652 }
3653 memset(&out, 0, sizeof(out));
3654 out.devices = audio_device; /* only field needed in select_devices */
3655 uc_info.stream.out = &out;
3656 uc_info.devices = audio_device;
3657 uc_info.in_snd_device = SND_DEVICE_NONE;
3658 uc_info.out_snd_device = SND_DEVICE_NONE;
3659 list_add_tail(&adev->usecase_list, &uc_info.list);
3660
3661 /* select device - similar to start_(in/out)put_stream() */
3662 retval = select_devices(adev, audio_usecase);
3663 if (retval >= 0) {
3664 *pparams = pcm_params_get(card_id, device_id, flags_dir);
3665#if LOG_NDEBUG == 0
3666 if (*pparams) {
3667 ALOGV("%s: (%s) card %d device %d", __func__,
3668 dir ? "input" : "output", card_id, device_id);
3669 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
Steve Kondik13582572015-12-05 17:19:19 -08003670 ALOGV("parms: %s", info); /* print parameters */
Steve Kondik3abbbc82014-11-29 14:14:43 -08003671 } else {
3672 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
3673 }
3674#endif
3675 }
3676
3677 /* deselect device - similar to stop_(in/out)put_stream() */
3678 /* 1. Get and set stream specific mixer controls */
3679 retval = disable_audio_route(adev, &uc_info);
3680 /* 2. Disable the rx device */
3681 retval = disable_snd_device(adev,
3682 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
3683 list_remove(&uc_info.list);
3684 }
3685 }
3686 adev->active_input = NULL; /* restore adev state */
3687 return 0;
3688}
3689
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690static int adev_close(hw_device_t *device)
3691{
Steve Kondik3abbbc82014-11-29 14:14:43 -08003692 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003693 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07003694
3695 if (!adev)
3696 return 0;
3697
3698 pthread_mutex_lock(&adev_init_lock);
3699
3700 if ((--audio_device_ref_count) == 0) {
Daniel Hillenbrand8373bc62013-05-23 10:10:00 +05303701 if (amplifier_close() != 0)
3702 ALOGE("Amplifier close failed");
Kiran Kandide144c82013-11-20 15:58:32 -08003703 audio_extn_listen_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07003704 audio_route_free(adev->audio_route);
3705 free(adev->snd_dev_ref_cnt);
3706 platform_deinit(adev->platform);
Eric Laurentda46bfb2014-08-25 22:39:29 -05003707 audio_extn_extspk_deinit(adev->extspk);
Steve Kondik3abbbc82014-11-29 14:14:43 -08003708 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
3709 pcm_params_free(adev->use_case_table[i]);
3710 }
Kiran Kandi910e1862013-10-29 13:29:42 -07003711 free(device);
3712 adev = NULL;
3713 }
3714 pthread_mutex_unlock(&adev_init_lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003715 return 0;
3716}
3717
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003718/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
3719 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
3720 * just that it _might_ work.
3721 */
3722static int period_size_is_plausible_for_low_latency(int period_size)
3723{
3724 switch (period_size) {
Glenn Kasten44b01922015-04-09 09:43:29 -07003725 case 48:
3726 case 96:
3727 case 144:
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003728 case 160:
Glenn Kasten44b01922015-04-09 09:43:29 -07003729 case 192:
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003730 case 240:
3731 case 320:
3732 case 480:
3733 return 1;
3734 default:
3735 return 0;
3736 }
3737}
3738
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003739static int adev_open(const hw_module_t *module, const char *name,
3740 hw_device_t **device)
3741{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003742 int i, ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003743
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003744 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003745 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
3746
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003747 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07003748 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003749 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07003750 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003751 ALOGD("%s: returning existing instance of adev", __func__);
3752 ALOGD("%s: exit", __func__);
3753 pthread_mutex_unlock(&adev_init_lock);
3754 return 0;
3755 }
3756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003757 adev = calloc(1, sizeof(struct audio_device));
3758
Haynes Mathew George9f0254a2014-06-30 13:56:18 -07003759 if (!adev) {
3760 pthread_mutex_unlock(&adev_init_lock);
3761 return -ENOMEM;
3762 }
3763
Ravi Kumar Alamanda33de8142014-04-24 10:34:41 -07003764 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
3765
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003766 adev->device.common.tag = HARDWARE_DEVICE_TAG;
3767 adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
3768 adev->device.common.module = (struct hw_module_t *)module;
3769 adev->device.common.close = adev_close;
3770
3771 adev->device.init_check = adev_init_check;
3772 adev->device.set_voice_volume = adev_set_voice_volume;
3773 adev->device.set_master_volume = adev_set_master_volume;
3774 adev->device.get_master_volume = adev_get_master_volume;
3775 adev->device.set_master_mute = adev_set_master_mute;
3776 adev->device.get_master_mute = adev_get_master_mute;
3777 adev->device.set_mode = adev_set_mode;
3778 adev->device.set_mic_mute = adev_set_mic_mute;
3779 adev->device.get_mic_mute = adev_get_mic_mute;
3780 adev->device.set_parameters = adev_set_parameters;
3781 adev->device.get_parameters = adev_get_parameters;
3782 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
3783 adev->device.open_output_stream = adev_open_output_stream;
3784 adev->device.close_output_stream = adev_close_output_stream;
3785 adev->device.open_input_stream = adev_open_input_stream;
3786 adev->device.close_input_stream = adev_close_input_stream;
3787 adev->device.dump = adev_dump;
3788
3789 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003790 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08003791 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003792 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003793 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08003795 adev->acdb_settings = TTY_MODE_OFF;
Eric Laurent07eeafd2013-10-06 12:52:49 -07003796 /* adev->cur_hdmi_channels = 0; by calloc() */
ApurupaPattapu9d6b4362014-02-27 10:24:11 -08003797 adev->cur_codec_backend_samplerate = CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
3798 adev->cur_codec_backend_bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Eric Laurentb23d5282013-05-14 15:27:20 -07003799 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07003800 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003801 list_init(&adev->usecase_list);
Krishnankutty Kolathappilly9b7e96b2014-02-14 14:45:49 -08003802 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy148144e2014-04-01 21:03:10 -07003803 adev->offload_usecases_state = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003804
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303805 pthread_mutex_init(&adev->snd_card_status.lock, (const pthread_mutexattr_t *) NULL);
3806 adev->snd_card_status.state = SND_CARD_STATE_OFFLINE;
3807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07003809 adev->platform = platform_init(adev);
3810 if (!adev->platform) {
3811 free(adev->snd_dev_ref_cnt);
3812 free(adev);
3813 ALOGE("%s: Failed to init platform data, aborting.", __func__);
3814 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08003815 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07003816 return -EINVAL;
3817 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003818
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303819 adev->snd_card_status.state = SND_CARD_STATE_ONLINE;
Eric Laurentda46bfb2014-08-25 22:39:29 -05003820 adev->extspk = audio_extn_extspk_init(adev);
Naresh Tanniru2d19ab42014-05-11 19:56:25 +05303821
Eric Laurentc4aef752013-09-12 17:45:53 -07003822 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
3823 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
3824 if (adev->visualizer_lib == NULL) {
3825 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
3826 } else {
3827 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
3828 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003829 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003830 "visualizer_hal_start_output");
3831 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003832 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07003833 "visualizer_hal_stop_output");
3834 }
3835 }
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003836 audio_extn_listen_init(adev, adev->snd_card);
Eric Laurentc4aef752013-09-12 17:45:53 -07003837
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003838 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
3839 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
3840 if (adev->offload_effects_lib == NULL) {
3841 ALOGE("%s: DLOPEN failed for %s", __func__,
3842 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3843 } else {
3844 ALOGV("%s: DLOPEN successful for %s", __func__,
3845 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
3846 adev->offload_effects_start_output =
3847 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3848 "offload_effects_bundle_hal_start_output");
3849 adev->offload_effects_stop_output =
3850 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
3851 "offload_effects_bundle_hal_stop_output");
3852 }
3853 }
3854
Dan Pasanend4c2ca92015-08-10 19:47:43 -05003855 if (amplifier_open() != 0)
3856 ALOGE("Amplifier initialization failed");
3857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003858 *device = &adev->device.common;
Steve Kondik3abbbc82014-11-29 14:14:43 -08003859 if (k_enable_extended_precision)
3860 adev_verify_devices(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003861
Kiran Kandi910e1862013-10-29 13:29:42 -07003862 audio_device_ref_count++;
Ravi Kumar Alamanda1c3de5e2014-09-08 15:59:58 -07003863
3864 char value[PROPERTY_VALUE_MAX];
3865 int trial;
3866 if (property_get("audio_hal.period_size", value, NULL) > 0) {
3867 trial = atoi(value);
3868 if (period_size_is_plausible_for_low_latency(trial)) {
3869 pcm_config_low_latency.period_size = trial;
3870 pcm_config_low_latency.start_threshold = trial / 4;
3871 pcm_config_low_latency.avail_min = trial / 4;
3872 configured_low_latency_capture_period_size = trial;
3873 }
3874 }
3875 if (property_get("audio_hal.in_period_size", value, NULL) > 0) {
3876 trial = atoi(value);
3877 if (period_size_is_plausible_for_low_latency(trial)) {
3878 configured_low_latency_capture_period_size = trial;
3879 }
3880 }
3881
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07003882 pthread_mutex_unlock(&adev_init_lock);
3883
Ravi Kumar Alamandad995c592015-09-23 13:47:03 -07003884 audio_extn_perf_lock_init();
3885
Eric Laurent994a6932013-07-17 11:51:42 -07003886 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003887 return 0;
3888}
3889
3890static struct hw_module_methods_t hal_module_methods = {
3891 .open = adev_open,
3892};
3893
3894struct audio_module HAL_MODULE_INFO_SYM = {
3895 .common = {
3896 .tag = HARDWARE_MODULE_TAG,
3897 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
3898 .hal_api_version = HARDWARE_HAL_API_VERSION,
3899 .id = AUDIO_HARDWARE_MODULE_ID,
3900 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08003901 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902 .methods = &hal_module_methods,
3903 },
3904};